【问题标题】:Using UITextViewDelegate in subclass and in UIViewController在子类和 UIViewController 中使用 UITextViewDelegate
【发布时间】:2021-05-02 03:11:06
【问题描述】:

我正在继承 UITextView 并在子类中实现一些委托方法,例如 textViewDidChangeSelection,但我还需要在 View Controller 中获取 UITextView 委托的通知。 因此,如果我创建子类的对象并在视图控制器中设置 textview 委托,则仅在视图控制器中而不是在子类中通知委托方法。我需要通知两个班级。我使用的语言是 swift 2

我尝试在子类委托中继承 UITextViewDelegate:

@objc protocol CustomTextViewDelegate:UITextViewDelegate {

    func customTextViewDidChangeSize(chatTextView: CustomTextView)

}

然后在 VC 中:

let customTV = CustomTextView()
customTV.customTextViewDelegate = self

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

【问题讨论】:

  • 你可以删除你的自定义文本视图,并从UIViewController 设置它,当你的文本视图告诉自己textViewDidChangeSelection 时,你会通过你的自定义委托告诉你的UIViewController
  • textview 委托中还有很多其他方法,我不想全部都这样做。有什么方法可以让我同时监听子类和 VC。
  • 您可以在自定义文本视图中设置代理,然后在ViewController 中设置如下:[texView addTarget:self action:@selector(textFieldDidChange:) forControlEvents:UIControlEventEditingChanged]; 更多信息here
  • addTarget 方法不适用于 textview。
  • 我的错,我想唯一的方法是像他的用户那样实现自定义委托。 UITextView delegate methods

标签: ios swift2 uitextview


【解决方案1】:

好问题。这是一个不太好的答案,因为它需要您重写所有委托方法,因此在委托方法随时间变化的情况下跨 iOS 版本并不稳定。

在这种方法中,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

【讨论】:

    【解决方案2】:

    两个对象不能同时委托给UITextView 对象。出于这个原因,您应该为您的 CustomTextView 创建新协议 (CustomTextViewDelegate) 并在其中创建委托属性。让你的ViewController 确认这个CustomTextViewDelegate 并实现它的方法。在 CustomTextViewUITextViewDelegate 方法实现中,您可以调用适当的 CustomTextViewDelegate 方法。

    【讨论】:

      【解决方案3】:

      @nayoti 的方法非常好。但是我必须做一些修复才能正常工作。主要是一些委托方法不会被调用(例如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
          }
          
      }
      

      【讨论】:

        猜你喜欢
        • 2015-08-28
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2016-04-23
        • 1970-01-01
        相关资源
        最近更新 更多