ios - 在委托(delegate)方法中使用默认行为对 UITextField 进行子类化的设计方法

标签 ios swift uitextfield uitextfielddelegate

我已经对 UITextField 类进行了子类化,因此我可以为我的应用程序提供一些内置功能。我更改了外观,只为用户体验设计提供下划线边框。另外,我想在有选择器(选择列表、日期/时间选择器)的情况下使用此控件。在这些情况下,我想阻止编辑,但我仍然需要响应触摸事件。为此,我添加了可检查的属性来从 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)
}

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

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

问题是如何在子类中提供这种默认行为?你可以这样做:

self.delegate = self

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

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

如果有一种干净的方法以封装的方式提供这种默认行为,那就最好了。

显然,还有许多其他方法可以解决此问题(即在 10 个 View Controller 中编写相同的代码)。从本质上讲,当像这样子类化控件时,似乎应该有办法重用委托(delegate)代码。

大家有什么想法吗?

最佳答案

您将采取的每一种方法都将是一种权衡。我认为对于此类问题没有一个完美干净的解决方案。从我的角度来看,最好的解决方案是将自定义 UITextField 实现为一种代理委托(delegate)。

您可以通过两种方式做到这一点。这是最简单的。

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)接口(interface),可以使用一个小技巧并覆盖 delegate 属性。

override var delegate: UITextFieldDelegate? {
    didSet {
        if delegate === self {
            return
        }            
        externalDelegate = delegate
        delegate = oldValue
    }
}

优点

  • 通过代码和 Storyboard 进行配置时效果良好。
  • 从客户端代码的角度来看,它是透明的。

缺点

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

关于ios - 在委托(delegate)方法中使用默认行为对 UITextField 进行子类化的设计方法,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58151254/

相关文章:

ios - 如何为 Swift 应用程序中的每个 View 编写不同的键盘处理?

ios - 按日期限制 iOS 应用程序的使用

ios - Swift optional 需要澄清

ios - 移动 UITextField 的左 View

swift - UITableView 作为 UITextField didSelectRowAtIndexPath 的 inputView 随机未触发

ios - 如何在成功登录后重置 touchIDLockout?

xcode - Realm - 模块文件是由旧版本的编译器创建的

ios - 不同的AVAudioQuality选项对生成的录音有什么影响?

ios - 将文本字段添加到 SKScene

ios - 轮播不起作用