-2

I have a protocol with some optional functions. My goal is to check if a delegate function is implemented by the delegate object, if yes execute it, otherwise do some default stuff.

I am using respondsToSelector for this purpose, it works fine for functions that with none or only one parameters, but doesn't work for two parameters.

Could anyone help? Thanks in advance.

Note that all the functions have been implemented by the delegate object, here is my code:

@objc protocol ViewControllerDelegate: NSObjectProtocol {

    optional func doSomethingWithoutParams()

    optional func doSomethingWithOneParam(controller: ViewController)

    optional func doSomethingWithTwoParams(controller: ViewController, secondParam: String)
}

class ViewController: UIViewController {

    weak var delegate: ViewControllerDelegate?

    @IBAction func onButtonClicked(sender: AnyObject){

        if (delegate != nil && delegate!.respondsToSelector(Selector("doSomethingWithoutParams"))) {

            // Entered here

        }
        else{
            NSLog("doSomethingWithoutParams is not implemented")
        }

        if (delegate != nil && delegate!.respondsToSelector(Selector("doSomethingWithOneParam:"))) {

            // Entered here

        }
        else{
            NSLog("doSomethingWithOneParam is not implemented")
        }

        if (delegate != nil && delegate!.respondsToSelector(Selector("doSomethingWithTwoParams::"))) {
            NSLog("doSomethingWithTwoParams is implemented")
        }
        else{

            // Entered here

            NSLog("doSomethingWithTwoParams is not implemented")
        }
    }
}
dichen
  • 1,643
  • 14
  • 19

2 Answers2

4

Using Selector(String) is now considered deprecated in Swift 2.2 (with Xcode 7.3) and will be removed in Swift 3, partly because it is error-prone.

A new syntax has been introduced in Swift 2.2: #selector(). It is type-safe and Xcode provides autocompletion as you type. For your code, the Selector(String) calls:

Selector("doSomethingWithoutParams")
Selector("doSomethingWithOneParam:")
Selector("doSomethingWithTwoParams::")

should be replaced by:

#selector(ViewControllerDelegate.doSomethingWithoutParams)
#selector(ViewControllerDelegate.doSomethingWithOneParam(_:)
#selector(ViewControllerDelegate.doSomethingWithTwoParams(_:secondParam:)
Valentin
  • 10,769
  • 2
  • 17
  • 27
0

I think I found the answer by my self, thanks to @Shripada, and the credit goes to https://stackoverflow.com/a/24168825/3543150.

You need to specify the parameterName in the Selector string:

    if (delegate != nil && delegate!.respondsToSelector(Selector("doSomethingWithTwoParams:secondParam:"))) {

        // Entered here now

        NSLog("doSomethingWithTwoParams is implemented")

        delegate!.doSomethingWithTwoParams!(self, secondParam: "dummy")
    }
    else{

        NSLog("doSomethingWithTwoParams is not implemented")
    }

And it's nicer to use optional chain for the checking:

    // Nicer way
    guard let _ = delegate?.doSomethingWithTwoParams?(self, secondParam: "dummt") else {

        NSLog("doSomethingWithTwoParams is not implemented, do some default stuff")

        return
    }
Community
  • 1
  • 1
dichen
  • 1,643
  • 14
  • 19