Swift-具有委托的自定义默认组件

时间:2018-10-20 00:58:55

标签: ios swift delegates uikit

我想通过继承默认的UITextView来编写自定义文本视图。我的实现使用原始组件委托中的一些方法:

class CustomTextView: UITextView {
    fileprivate func applyStyles() {
        self.layer.cornerRadius = 5
        self.layer.borderColor = .black
        self.layer.borderWidth = 5
        self.clipsToBounds = true
    }

    override func awakeFromNib() {
        super.awakeFromNib()
        applyStyles()
        delegate = self
    }    
}

extension CustomTextView: UITextViewDelegate {
    func textViewDidBeginEditing(_ textView: UITextView) {
        print("aaaa")
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        print("bbbb")
    }
}

现在,我想在各处而不是标准视图中使用此文本视图,但是在当前实现中,我失去了在不丢失我自己的委托函数的情况下为该组件设置另一个委托的能力。 我的意思是,如果我要在其他类中创建这样的组件:

let customView = CustomTextView()
customView.delegate = self
CustomTextView中的

textViewDidBeginEditing和textViewDidEndEditing函数将不会被调用。我如何解决这个限制?谢谢。

2 个答案:

答案 0 :(得分:1)

诀窍是重写delegate属性,以便您可以捕获分配的任何值,然后在代码完成后调用该委托。为此,您的子类将需要实现UITextViewDelegate函数的 all ,以便将调用传递给“真实”委托:

class CustomTextView: UITextView {

    private weak var externalDelegate: UITextViewDelegate?

    override var delegate: UITextViewDelegate? {
        set {
            self.externalDelegate = newValue
        }

        get {
            return self.externalDelegate
        }
    }

    fileprivate func applyStyles() {
        self.layer.cornerRadius = 5
        self.layer.borderColor = UIColor.black.cgColor
        self.layer.borderWidth = 5
        self.clipsToBounds = true
    }

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

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

extension CustomTextView: UITextViewDelegate {
    func textViewDidBeginEditing(_ textView: UITextView) {
        print("aaaa")
        self.externalDelegate?.textViewDidBeginEditing?(textView)
    }

    func textViewDidEndEditing(_ textView: UITextView) {
        print("bbbb")
        self.externalDelegate?.textViewDidEndEditing?(textView)
    }

    func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
        return self.externalDelegate?.textViewShouldEndEditing?(textView) ?? true
    }

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

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

    func textViewDidChange(_ textView: UITextView) {
        self.externalDelegate?.textViewDidChange?(textView)
    }

    func textViewDidChangeSelection(_ textView: UITextView) {
            self.externalDelegate?.textViewDidChangeSelection?(textView)
    }

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

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

}

答案 1 :(得分:0)

尽管您可能希望在自定义textview类和parentVc中都触发回调,但原因可能尚不清楚,但是您可以这样做

class CustomTextView: UITextView , UITextViewDelegate {
   weak var parentVC:VCName?

 func textViewDidBeginEditing(_ textView: UITextView) {
    print("aaaa")
    parentVC?.textViewDidBeginEditing(self)
 }

let customView = CustomTextView()
customView.parentVC = self

或执行相反的操作,即以parentVc作为委托并从中调用textView子类的方法