Implement selector method in protocol extension

I want to implement some NSNotificationCenter selector method in protocol extension. The reason is extensibility some mechanism for few ViewControllers. But this doesn't work. I have error: unrecognized selector.

Ok, I make some test like this:


protocol SomeProtocol{
    func xyz()->Void
}
class BigData : NSObject, SomeProtocol{
    func xyz() {
        /
    }
}
let big = BigData()
big.respondsToSelector("xyz")

It works fine - respondsToSelector() returns true, but if I write the code in protocol extension:

extension SomeProtocol{
    func xyz(){
       
    }
}

then respondsToSelector() return false. My question is: why? How can I fix this? I really need this mechanism.

Accepted Reply

I think you have probably found a bug. I would expect it to work. It might be a bug that is a fring case, using Objective-C RTTI within Swift, and therefore it might not be a high priority fix 😟.


Can you use this as a work around?


protocol ABCProtocol {
    func abc() -> String
}
protocol XYZABCProtocol: ABCProtocol {
    func xyz() -> String
}
class BigData: XYZABCProtocol {
    func xyz() -> String {
        return "XYZABC"
    }
    func abc() -> String {
        return "ABC"
    }
}
func test(abc: ABCProtocol) -> String {
    if let xyzabc = abc as? XYZABCProtocol {
        return xyzabc.xyz()
    } else {
        return abc.abc()
    }
}
let big = BigData()
test(big) // XYZABC

Replies

Did you mean to write this?

extension BigData: SomeProtocol {
    func xyz() {
          // do something
    }
}


The way you wrote it, you were extending the protocol, not the class. You need to write the extension on the class in order for it to actually work.

I know about it, but I want to deliver common functionality to few ViewControllers, so I create protocol and default implementations of his methods by protocol extension. Similar problem you can find here: https://forums.developer.apple.com/thread/16773

I see what you mean. If all you're trying to do is provide common functionality for several view controllers, why not write the extension on NS/UIViewController, like this:

extension NSViewController: SomeProtocol { 
    func xyz() { 
          // do something 
    } 
}


This way all of your subclasses will be able to use the function.

Because then all ViewControllers will have this method which is not desirable because my protocol also have some properties.. and imo this is not good practise. Why my solution do not work?

I think you have probably found a bug. I would expect it to work. It might be a bug that is a fring case, using Objective-C RTTI within Swift, and therefore it might not be a high priority fix 😟.


Can you use this as a work around?


protocol ABCProtocol {
    func abc() -> String
}
protocol XYZABCProtocol: ABCProtocol {
    func xyz() -> String
}
class BigData: XYZABCProtocol {
    func xyz() -> String {
        return "XYZABC"
    }
    func abc() -> String {
        return "ABC"
    }
}
func test(abc: ABCProtocol) -> String {
    if let xyzabc = abc as? XYZABCProtocol {
        return xyzabc.xyz()
    } else {
        return abc.abc()
    }
}
let big = BigData()
test(big) // XYZABC

For my code example it works fine but my real task is much more expanded.

Anyway thank you. Now we can have only hope that Apple fix this bug.