在委托方法中使用默认行为将UITextField子类化的设计方法 [英] Design Approach for Subclassing UITextField with default behaviors in delegate methods

查看:64
本文介绍了在委托方法中使用默认行为将UITextField子类化的设计方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我将UITextField类子类化,因此我可以为我的应用程序提供一些内置功能.我更改了外观,仅为UX设计提供了下划线边框.另外,我想在有选择器(选择列表,日期/时间选择器)的情况下使用此控件.在这些情况下,我想防止编辑但我仍然需要响应触摸事件.为此,我添加了可检查的属性以通过IB对其进行控制.

I have subclassed the UITextField class so I can provide some built-in functionality for my application. I've changed the appearance to provide only an underline border for the UX design. Also, I want to use this control in situations where there is a picker (pick list, date / time picker). In these cases, I want to prevent editing BUT I still need to respond to touch events. To do this, I've added inspectable properties to control it from IB.

通过执行以下操作,我可以轻松阻止复制/粘贴菜单的出现:

I can easily prevent the copy/paste menu from appearing by doing this:

    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)
}

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

However, I need to prevent them from typing or deleting characters in the textfield after something is selected in the picker. Typically, you would use the following delegate method:

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

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

The question is how do you provide this kind of default behavior in a subclass? You could do a:

self.delegate = self

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

However, this leads to all sorts of shortcomings so it's not a good solution.

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

The other solution would be to implement a base UIViewController subclass (MyBaseViewController) but this would lead to convoluted and monolithic code later on.

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

It would be best if there was a clean way to provide this kind of default behavior in an encapsulated manner.

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

Obviously, there are a number of other ways to fix this (i.e. write the same code in 10 view controllers). Essentially, it seems there should be way to reuse delegate code when subclassing controls like this.

有人有什么想法吗?

推荐答案

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

Every approach you will take will be a trade-off. I don't think there is a perfectly clean solution for this type of problem. From my point of view, the best solution is to implement your custom UITextField as a kind of proxy delegate.

您可以通过两种方式进行操作.这是最简单的一个.

You can do it in two ways. This is the simplest one.

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属性.

If you don't want to modify the delegation interface for your custom control, you can do a small trick and overwrite the delegate property.

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

专业人士

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

    • Works well when configured from code and from storyboard.
    • It's transparent from the client code perspective.
    • 此方法附带的缺点是,您必须在UITextField子类中实现UITextFieldDelegate协议中的每个方法,以完全支持委托.幸运的是,其中只有8个,几乎不需要全部,因此可以将其缩小到所需的子集.

      The drawback which comes with this approach is that you have to implement every method from the UITextFieldDelegate protocol in your UITextField subclass to fully support the delegation. Fortunately, there are only 8 of them and it's unlikely that you will need all, so you can narrow it down to the required subset.

      这篇关于在委托方法中使用默认行为将UITextField子类化的设计方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆