How to set delegate in a protocol extension for a UIkit class

Paul Mayer

I'm trying to have all my TextView instances use this same delegate function from UITextPasteDelegate without copying the delegate function into each VC.

Xcode 10.3 compiler doesn't throw an error when I do this:

extension UITextView : UITextPasteDelegate {

     private func textPasteConfigurationSupporting(_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting, shouldAnimatePasteOf attributedString: NSAttributedString, to textRange: UITextRange) -> Bool {
          return false
     }
}

However the problem I run into is when I try to set this delegate in my VC. The code looks something like this:

class viewController : UIViewController{

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()

        textView.pasteDelegate = self
    }
}

It breaks on the line textView.pasteDelegate = self and I understand that it breaks here because the viewController class is not implementing UITextPasteDelegate. But my question is whether it is possible to assign textView.pasteDelegate = ? to something. I've tried textView.pasteDelegate = UITextView.Type but that also fails.

Is there a way to achieve this?

Rob Napier

Extensions cannot override methods. This is not supported. Sometimes it may happen to work, but it is undefined behavior.

From Extensions in The Swift Programming Language:

Extensions can add new functionality to a type, but they cannot override existing functionality.

(This is all true, but doesn't actually apply to this question; see more below.)

This is exactly what subclasses are for. In Interface Builder, select your subclass and it'll still wire up as a UITextView. It'll just be configured the way you want. For example:

class NonAnimatingTextView: UITextView {
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        super.init(frame: frame, textContainer: textContainer)
        self.pasteDelegate = self
    }

    required init?(coder: NSCoder) {
        super.init(coder: coder)
    }
}

extension NonAnimatingTextView: UITextPasteDelegate {
    func textPasteConfigurationSupporting(
        _ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting,
        shouldAnimatePasteOf attributedString: NSAttributedString,
        to textRange: UITextRange) -> Bool { false }
}

For completeness, the exact thing you're trying to do is in fact possible; it's just not the right approach. (In this case it works out that it's not an override, so it's possible.)

First, you marked the method as private when it should be public and ideally @objc (@objc may not be required here, but I would add it to be very clear):

extension UITextView : UITextPasteDelegate {
     @objc public func textPasteConfigurationSupporting(_ textPasteConfigurationSupporting: UITextPasteConfigurationSupporting, shouldAnimatePasteOf attributedString: NSAttributedString, to textRange: UITextRange) -> Bool {
          return false
     }
}

And then the UITextView is its own pasteDelegate:

class ViewController : UIViewController{

    @IBOutlet weak var textView: UITextView!

    override func viewDidLoad() {
        super.viewDidLoad()    
        textView.pasteDelegate = textView
    }
}

But I still recommend the subclass. It's much clearer what you're doing.

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related

weak Delegate and class protocol

How can I set the delegate for a protocol from the child of the destination VC?

How to set delegate of UITextField in separate class in Swift?

Protocol Delegate Concept With Base Class

How to use a generic protocol as a delegate?

How to define variable that can be set and get in extension of protocol

Extension of a protocol where the associatedType is class?

How to set a delegate view controller class in a "model" component in Swift

How to point a delegate to an extension method

How to navigate from widget extension to UIKit viewController?

Where and how to set protocol delegate when slide out menu implemented in navigation controller?

How do you create a base class with a weak delegate that conforms to a generic protocol?

How to set UIView delegate?

How to set a delegate in Swift

Swift protocol extension with method in wrong delegate still works(?!)

How to delegate to implementing class

How can i update my ViewController UI using this extension delegate in another class

how to declare NFCReadersession variable in main class when NFC delegate method are implemented using extension?

How to define initializers in a protocol extension?

How to implement the CustomStringConvertible for a protocol in extension?

Swift Class Extension Only When Conforming to Protocol

Swift extension only when conforming to Class AND protocol

Conform class extension to generic protocol function

Calling class properties from within protocol extension

Protocol Extension in Swift Where Object Is a Class and conforms to a Protocol

@obj protocol delegate method not working in second class. Swift

How to get current extension delegate on watchOS?

How to Access DAC Extension on Action Delegate

How to set custom delegate to UITableViewController?