我已经将UITextField类子类化,因此我可以为我的应用程序提供一些内置功能。我改变了外观,只为UX设计提供了下划线边框。此外,我想在有选择器(选择列表,日期/时间选择器)的情况下使用此控件。在这些情况下,我想阻止编辑,但我仍然需要响应触摸事件。为此,我添加了可检查属性以从IB控制它。
我可以通过这样做轻松阻止复制/粘贴菜单出现:
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if isFirstResponder && disableEditing {
DispatchQueue.main.async(execute: {
(sender as? UIMenuController)?.setMenuVisible(false, animated: false)
})
return false
}
return super.canPerformAction(action, withSender: sender)
}
但是,我需要阻止他们在选择器中选择某些内容后在文本字段中键入或删除字符。通常,您将使用以下委托方法:
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return false
}
问题是你如何在子类中提供这种默认行为?你可以做:
self.delegate = self
然而,这会导致各种缺点,因此它不是一个好的解决方案。
另一个解决方案是实现一个基本的UIViewController子类(MyBaseViewController),但这会导致以后出现错综复杂的单片代码。
如果有一种干净的方式以封装的方式提供这种默认行为,那将是最好的。
显然,还有很多其他方法可以解决这个问题(即在10个视图控制器中编写相同的代码)。从本质上讲,似乎应该有方法在子类化这样的控件时重用委托代码。
任何人有任何想法吗?
答案 0 :(得分:4)
您将采取的每一种方法都将是一种权衡。我不认为这种问题有一个非常干净的解决方案。从我的角度来看,最好的解决方案是将自定义class CustomTextField: UITextField, UITextFieldDelegate
{
var externalDelegate: UITextFieldDelegate?
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
delegate = self
}
func textFieldDidBeginEditing(_ textField: UITextField) {
externalDelegate?.textFieldDidBeginEditing?(textField)
}
}
实现为一种代理委托。
你可以用两种方式做到这一点。这是最简单的一个。
delegate
如果您不想修改自定义控件的委派界面,可以执行一个小技巧并覆盖override var delegate: UITextFieldDelegate? {
didSet {
if delegate === self {
return
}
externalDelegate = delegate
delegate = oldValue
}
}
属性。
UITextFieldDelegate
此方法带来的缺点是您必须实现UITextField
子类中grep ^roll students.txt
协议的每个方法,以完全支持委派。幸运的是,它们中只有8个并且您不太可能需要所有这些,因此您可以将其缩小到所需的子集。