在委托方法中使用默认行为将UITextField子类化的设计方法

Sha*_*awn 2 uitextfield ios uitextfielddelegate swift

我已经对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)
}
Run Code Online (Sandbox Code Playgroud)

但是,在选择器中选择某些内容后,我需要防止它们在文本字段中键入或删除字符。通常,您将使用以下委托方法:

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    return false
}
Run Code Online (Sandbox Code Playgroud)

问题是如何在子类中提供这种默认行为?您可以执行以下操作:

self.delegate = self
Run Code Online (Sandbox Code Playgroud)

但是,这会导致各种各样的缺点,所以这不是一个好的解决方案。

另一种解决方案是实现一个基本的UIViewController子类(MyBaseViewController),但是稍后将导致复杂的代码。

最好有一种干净的方法以封装的方式提供这种默认行为。

显然,还有许多其他方法可以解决此问题(即在10个视图控制器中编写相同的代码)。本质上,在子类化控件时,似乎应该有一种方法可以重用委托代码。

有人有想法么??

Kam*_*ski 5

您将采用的每一种方法都是一个折衷方案。对于这种类型的问题,我认为没有完美的解决方案。从我的角度来看,最好的解决方案是将您的自定义实现UITextField为一种代理委托。

您可以通过两种方式来实现。这是最简单的。

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)
    }
}
Run Code Online (Sandbox Code Playgroud)

如果您不想为自定义控件修改委托接口,则可以做一些小技巧并覆盖该delegate属性。

override var delegate: UITextFieldDelegate? {
    didSet {
        if delegate === self {
            return
        }            
        externalDelegate = delegate
        delegate = oldValue
    }
}
Run Code Online (Sandbox Code Playgroud)

优点

  • 从代码和情节提要中进行配置时,效果很好。
  • 从客户端代码角度看,它是透明的。

缺点

这种方法的缺点是您必须UITextFieldDelegateUITextField子类中实现协议中的每种方法,以完全支持委托。幸运的是,它们只有8个,不太可能需要全部,因此您可以将其范围缩小到所需的子集。