swift2 在子类和UIViewController中使用UITextViewDelegate

z9zf31ra  于 2022-11-06  发布在  Swift
关注(0)|答案(3)|浏览(178)

我正在对UITextView进行子类化,并在子类(如textViewDidChangeSelection)中实现一些委托方法,但我还需要在视图控制器中获得UITextView委托的通知。因此,如果我创建子类的对象并在视图控制器中设置textview委托,则只会在视图控制器中通知委托方法,而不会在子类中通知。我需要同时通知这两个类。我使用的语言是swift 2
我试图继承子类中的UITextViewDelegate委托:

@objc protocol CustomTextViewDelegate:UITextViewDelegate {

    func customTextViewDidChangeSize(chatTextView: CustomTextView)

}

然后在VC中:

let customTV = CustomTextView()
customTV.customTextViewDelegate = self

但没有调用任何textview委托方法。

vfwfrxfs

vfwfrxfs1#

问得好。这里有一个不太好的答案,因为它需要你重写所有的delegate-method,因此在iOS版本之间不稳定,以防delegate-method随时间变化。
在这种方法中,ViewControllerCustomTextField都可以访问委托事件。

class CustomTextView: UITextView {
   override var delegate: UITextViewDelegate? {
      set {
         superDelegate = newValue
      } get {
         return superDelegate
      }
    }

    private weak var superDelegate: UITextViewDelegate?

    init() {
       super.init(frame: .zero, textContainer: nil)
       super.delegate = self
    }

    func textDidChange(text: String?) {
        // do something
    }

}

extension BoundTextView: UITextViewDelegate {
    public func textViewDidChange(_ textView: UITextView) {
        // catch text-change events here
        textDidChange(text: String?) 
        superDelegate?.textViewDidChange?(textView)
    }

    public func textViewDidEndEditing(_ textView: UITextView) {
        superDelegate?.textViewDidEndEditing?(textView)
    }

    public func textViewDidChangeSelection(_ textView: UITextView) {
        superDelegate?.textViewDidChange?(textView)
    }

    public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
       return superDelegate?.textViewShouldBeginEditing?(textView) ?? false
    }

    public func textViewDidBeginEditing(_ textView: UITextView) {
        superDelegate?.textViewDidBeginEditing?(textView)
    }

    public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
       return superDelegate?.textViewShouldEndEditing?(textView) ?? false
    }

    public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        return superDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? false
    }

    public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        return superDelegate?.textView?(textView, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? false
    }

    public func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        return superDelegate?.textView?(textView, shouldInteractWith: textAttachment, in: characterRange, interaction: interaction) ?? false
    }
}

我们重写delegate,并在一个单独的变量(称为superDelegate)中存储对它的引用。CustomTextField将其自身分配给super.delegate,并实现UITextView-delegate。我们必须确保每个委托事件都触发相应的superDelegate的事件。
我们的'ViewController'现在可以将自己指定为CustomTextView的委托:

class ViewController: UIViewController {

   ...
   lazy var textField: CustomTextView {
      let textView = CustomTextField()
      textView.delegate = self 
      return textField
   }()
   ...

}

extension ViewController: UITextViewDelegate {

   // implement only the delegate-methods you need

}

现在,ViewControllerCustomTextField都可以访问UITextFieldDelegate

oxalkeyp

oxalkeyp2#

两个对象不能同时委托给UITextView对象。因此,您应该创建新协议(CustomTextViewDelegate)并在其中创建委托属性。使您的ViewController确认此CustomTextViewDelegate并实现它的方法。在您的CustomTextView中'UITextViewDelegate方法的实现,您可以调用相应的CustomTextViewDelegate方法。

fwzugrvs

fwzugrvs3#

@nayooti的方法非常好。但是我必须做一些修正才能正常工作。主要的一点是一些委托方法不会被调用(例如shouldChangeTextIn range,因此textViewDidChange也是)。
我发现可以通过在被覆盖的delegate变量的get访问器上返回super.delegate而不是superDelegate来修复这个问题。

class CustomTextView: UITextView {

    override var delegate: UITextViewDelegate? {
        set {
            superDelegate = newValue
        } get {
            return super.delegate
        }
    }

    private weak var superDelegate: UITextViewDelegate?

    init() {
        super.init(frame: .zero, textContainer: nil)
        super.delegate = self
    }

    override public init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        super.delegate = self
    }

    required public init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        super.delegate = self
    }

    func textDidChange(text: String?) {
        // Do something
    }

}

extension CustomTextView: UITextViewDelegate {

    public func textViewDidChange(_ textView: UITextView) {
        // Catch text-change events here
        textDidChange(text: textView.text)
        superDelegate?.textViewDidChange?(textView)
    }

    public func textViewDidEndEditing(_ textView: UITextView) {
        superDelegate?.textViewDidEndEditing?(textView)
    }

    public func textViewDidChangeSelection(_ textView: UITextView) {
        superDelegate?.textViewDidChange?(textView)
    }

    public func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        return superDelegate?.textViewShouldBeginEditing?(textView) ?? true
    }

    public func textViewDidBeginEditing(_ textView: UITextView) {
        superDelegate?.textViewDidBeginEditing?(textView)
    }

    public func textViewShouldEndEditing(_ textView: UITextView) -> Bool {
        return superDelegate?.textViewShouldEndEditing?(textView) ?? true
    }

    public func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool {
        return superDelegate?.textView?(textView, shouldChangeTextIn: range, replacementText: text) ?? true
    }

    public func textView(_ textView: UITextView, shouldInteractWith URL: URL, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        return superDelegate?.textView?(textView, shouldInteractWith: URL, in: characterRange, interaction: interaction) ?? true
    }

    public func textView(_ textView: UITextView, shouldInteractWith textAttachment: NSTextAttachment, in characterRange: NSRange, interaction: UITextItemInteraction) -> Bool {
        return superDelegate?.textView?(textView, shouldInteractWith: textAttachment, in: characterRange, interaction: interaction) ?? true
    }

}

相关问题