Swift - пользовательский компонент по умолчанию с делегатом - PullRequest
0 голосов
/ 20 октября 2018

Я хочу написать собственное текстовое представление, унаследовав 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

textViewDidBeginEditing и textViewDidEndEditing функции в CustomTextView не будут вызываться.Как я могу обойти это ограничение?Спасибо.

Ответы [ 2 ]

0 голосов
/ 20 октября 2018

Хитрость заключается в том, чтобы переопределить свойство delegate, чтобы вы могли захватить любое назначенное значение и затем вызвать этот делегат после выполнения кода.Чтобы это работало, вашему подклассу необходимо реализовать все функций UITextViewDelegate, чтобы передать вызов «реальному» делегату:

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
    }

}
0 голосов
/ 20 октября 2018

Несмотря на то, что причина может быть неясной из-за того факта, что вы хотите, чтобы обратный вызов запускался как внутри пользовательского класса 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

...