5

I'm trying to create a protocol that would be implemented by certain classes, all of them should also implement UIScrollViewDelegate. What I thought of is for my new protocol to implement the protocol UIScrollViewDelegate.

protocol MyProtocol: UIScrollViewDelegate {
    var myVar: NSString { get }
    func myMethod()
}

As the protocol should have its default implementation I also created an extension for this protocol.

extension MyProtocol {
    func myMethod() {
        print("I'm printing")
    }

    func scrollViewDidScroll(scrollView: UIScrollView) {
        print("I'm scrollin")
    }
}

It compiles, but does not work. What am I doing wrong and what would be the right way to create a default implementation of expanded protocol?

Eryk Sajur
  • 51
  • 1
  • 4
  • I think you are on the right track. My guess is that you have to override the setter for the delegate in your protocol and call super.delegate = theDelegate – oyvindhauge Feb 09 '16 at 12:50
  • 1
    What do you mean "it does not work". What happens? That's not an acceptable description of the problem. – nhgrif Feb 09 '16 at 12:57
  • At the first glance you are on the right track, but as of Swift 2.2, delegate methods defined in protocol extensions are not "found" from Objective-C code. You need to extend the class that conforms to `UIScrollViewDelegate`, that is define an extension method `scrollViewDidScroll` in a concrete class `MyScrollViewDelegate` or `MyScrollViewViewController`. – CouchDeveloper Feb 09 '16 at 12:57
  • @nhgrif it means the function is not entered – Eryk Sajur Feb 10 '16 at 07:26

1 Answers1

5

What you want to do is the following:

protocol MyProtocol{
    var myVar: NSString { get }
    func myMethod()
}

protocol MyProtocol2{
    var myVar2: NSString { get }
    func myMethod2()
}

extension MyProtocol where Self: MyProtocol2 {
    func myMethod() {
        print("I'm printing ")
    }
}

class anotherClass: MyProtocol, MyProtocol2 {
    var myVar: NSString {
        return "Yo"
    }

    var myVar2: NSString {
        return "Yo2"
    }

    func myMethod2() {
        print("I'm printing in myMethod2")
    }
}

In the above code MyProtocol2 is equivalent to your UIScrollViewDelegate,

hence what you will do is:

protocol MyProtocol{
    var myVar: NSString { get }
    func myMethod()
}

extension MyProtocol where Self: UIScrollViewDelegate {
    func myMethod() {
        print("I'm printing")
    }
}

class anotherClass: NSObject, MyProtocol, UIScrollViewDelegate {
    var myVar: NSString {
        return "Yo"
    }
}

Notice that another class subclasses NSObject, this is because if you do not do so, you will get the error

anotherClass does not conform to protocol NSObjectProtocol

This error is because UIScrollViewDelegate itself is defined to be extending NSObjectProtocol which is an objective-C protocol implemented by NSObject.

So make your class inherit from NSObject to conform to the NSObjectProtocol. Vanilla Swift classes do not.

Sumeet
  • 1,055
  • 8
  • 18
  • I want to move this functions implementation out of class' body, as it is supposed to act the same way in each class that implements the protocol. I know it is not what protocols are meant for, but I want to create a protocol extension with implementation of method from the other protocol (which is implemented by the primary one). – Eryk Sajur Feb 10 '16 at 07:33
  • yes you can still implement the methods of UIScrollViewDelegate in the protocol extension – Sumeet Feb 10 '16 at 07:53
  • Thanks for the answer @uchiha I tried doing this for where `anotherClass` is a subclass of `UIViewController`, which is already a descendant of `NSObject`, but the `scrollViewDidScroll(_ scrollView: UIScrollView)` function in the `UIScrollViewDelegate` is not correctly overridden. It seems like I only added another version of `scrollViewDidScroll` to my class. I understand that with the method you described, you'll be able to satisfy one protocol with functions from another protocol, but would you ever be able to create a default implementation for the `scrollViewDidScroll` function? – gokeji May 11 '17 at 02:35