35

I have a swift protocol:

@objc protocol SomeDelegate {

  optional func myFunction()

}

I one of my classes I did:

weak var delegate: SomeDelegate?

Now I want to check if the delegate has myFunction implemented.

In objective-c I can do:

if ([delegate respondsToSelector:@selector(myFunction)]) { 
...
}

But this is not available in Swift.

Edit: This is different from: What is the swift equivalent of respondsToSelector? I focus on class protocols not on classes.

How do I check if my delegate has an optional method implemented?

Community
  • 1
  • 1
Michael
  • 32,527
  • 49
  • 210
  • 370
  • Are you sure that this http://stackoverflow.com/a/27665147/1187415 or this http://stackoverflow.com/a/28078301/1187415 answer to the referenced thread does not answer your question? – Martin R May 22 '15 at 14:28
  • Don't now what version of Swift was available when the question was asked, but in swift 2.2 you can use respondsToSelector – the Reverend May 18 '16 at 15:48

6 Answers6

31

Per The Swift Programming Language:

You check for an implementation of an optional requirement by writing a question mark after the name of the requirement when it is called, such as someOptionalMethod?(someArgument). Optional property requirements, and optional method requirements that return a value, will always return an optional value of the appropriate type when they are accessed or called, to reflect the fact that the optional requirement may not have been implemented.

So the intention is not that you check whether the method is implemented, it's that you attempt to call it regardless and get an optional back.

Tommy
  • 99,986
  • 12
  • 185
  • 204
  • 1
    I want to check if the optional methods exist before I call it. – Michael May 22 '15 at 14:10
  • 3
    Then you probably don't want to use Swift. It's not what the language is crafted to support. What's your actual use case? – Tommy May 22 '15 at 14:11
  • 3
    @confile: Have a look at *all* answers to the "duplicate question", for example this one: http://stackoverflow.com/a/27665147/1187415. It shows how to test first if the delegate implements the method, and then call it. – Martin R May 22 '15 at 14:14
  • @Tommy While one should strive to follow conventions, there are cases where it could be handy to know if an optional method is actually implemented or not. In my case, the implementation of an optional method communicates whether or not a plugin handles a certain optional job or not. – devios1 Mar 06 '16 at 04:41
  • Yes, I could bake this into the plugin interface itself, but requiring that the developer return a boolean to indicate handled or not, for example, not only burdens the developer, but introduces the potential for bugs that could be avoided by simply checking if the method were implemented or not. – devios1 Mar 07 '16 at 23:09
  • 2
    If the optional method returns an optional type. you could be a bit stuck if you actually want to know the difference. – Mark Patterson May 11 '16 at 02:52
17

You can do

if delegate?.myFunction != nil {

}
newacct
  • 119,665
  • 29
  • 163
  • 224
8

I've found it successful to add an extension to the protocol that defines basic default implementation and then any class implementing the protocol need only override the functions of interest.

    public protocol PresenterDelegate : class {
        func presenterDidRefreshCompleteLayout(presenter: Presenter)
        func presenterShouldDoSomething(presenter: Presenter) -> Bool
    }

then extend

    extension PresenterDelegate {
        public func presenterDidRefreshCompleteLayout(presenter: Presenter) {}
        public func presenterShouldDoSomething(presenter: Presenter) -> Bool {
        return true
        }
    }

Now any class needing to conform to the PresenterDelegate protocol has all functions already implemented, so it's now optional to override it's functionality.

Chris
  • 2,727
  • 2
  • 27
  • 28
  • Looks very useful to know, if I can only remember it when I need it :-) – clearlight Dec 10 '16 at 20:54
  • Yeah but how does this work if some piece of code needs to take action only if the function is implemented? And it won't compile if `@objc` is required due to some part of the protocol's code calling #selector because it's doing something with UI. Hmmm. – xaphod Mar 26 '17 at 03:44
2

I normally implement it like this:

self.delegate?.myFunction?()

if the delegate methods returns a value:

var result = defaultValue
if let delegateResult = self.delegate?.myFunction?() else {
  result = delegateResult
}

//do something with result
0

Declaration

@objc public protocol nameOfDelegate: class {
    @objc optional func delegateMethod(_ varA: int, didSelect item: Item)
}

Implimetation

if let delegate = nameOfDelegate {
     delegate.delegateMethod?(1, didDeselect: node)
}
Darshit Shah
  • 2,366
  • 26
  • 33
0

I know this question is 5 years old, but I would like to share what I found. My solution works as of 2021, XCode 11+, Swift 5.

enter image description here

Say I wanted to figure out whether the function sign follows the GIDSignInDelegate protocol and also know what all the optional functions for GIDSignInDelegate are.

I have to look at the source code of the GIDSignIn module, and this is how.

enter image description here

Click on jump to definition on the main module that is imported. It will lead to a file like this:

enter image description here

Copy the entire line, import GoogleSignIn.GIDSignIn and paste it in the ViewController or whatever .swift file (doesn't really matter).

Within the swift file, right click on the GIDSignIn part of the import line GoogleSignIn.GIDSignIn and jump to definition. This will lead you to the actual module with all the available functions (the functions not marked optional may be stubs, which are required functions in the delegate protocol):

enter image description here

From this file, I can see that there is a sign function that is a stub of GIDSignInDelegate and an optional sign function that is implemented as a method overload.

I used this for GIDSignInDelegate, but you can use the same method to figure out whether any function follows any delegate protocol.

Wonjae Oh
  • 33
  • 7