3

I'm trying to write the following ObjC code in Swift 3:

- (void)scrollViewScroll:(UIScrollView*)scrollView {
    // some code
    if ([_userDelegate respondsToSelector:_cmd]) {
        [_userDelegate scrollViewDidEndDecelerating:scrollView];
    }
}

But do not know what to replace _cmd with. I'm trying function, but it doesn't work:

func scrollViewDidScroll(_ scrollView: UIScrollView) {
    // some code
    if (userDelegate?.responds(to: #function))! {
        userDelegate?.scrollViewDidScroll!(scrollView)
    }
}

using #selector(scrollViewDidScroll(_:)) works, but is there a way to keep it generic?

Edit: Possible duplicate answer is about getting function name which isn't what I'm asking above

Alexandre G
  • 1,655
  • 20
  • 30
  • Possible duplicate of [What is the swift equivalent to \_cmd?](http://stackoverflow.com/questions/24482670/what-is-the-swift-equivalent-to-cmd) – i_am_jorf Dec 09 '16 at 05:10
  • @i_am_jorf I've seen that answer, but using #function, as you can see, does not work.. – Alexandre G Dec 09 '16 at 05:14
  • The accepted answer on that question is more relevant to you than the highest-voted answer. – jtbandes Dec 09 '16 at 05:39
  • @jtbandes Hi, yes, thanks, I sort of see, but still doubt that there is no way to do it after two more years of swift evolution, and as that question wasn't asking the same thing decided to ask this one – Alexandre G Dec 09 '16 at 06:01
  • No, there is no way. This was discussed pretty recently: https://www.mail-archive.com/swift-evolution@swift.org/msg18521.html – jtbandes Dec 09 '16 at 06:10

1 Answers1

2

Swift doesn't have selectors. Objective-C sends messages to objects while Swift calls functions. So checking if object can respond to selector is part of Objective-C and NSObject.

Swift protocol functions are required by default. Swift compiler doesn't let you skip those function implementations. But you can make them optional, and you have to check, if these functions implemented before calling.

In this case, just call function with question mark at the end, like this

if let returnValue = userDelegate?.theOptionalFunction?(arguments) {
    // you got value
} else {
    // delegate returned nil or delegate function isn't implemented
}

Source: The Swift Programming Language

An optional protocol requirement can be called with optional chaining, to account for the possibility that the requirement was not implemented by a type that conforms to the protocol. You check for an implementation of an optional method by writing a question mark after the name of the method when it is called, such as someOptionalMethod?(someArgument).

GRiMe2D
  • 654
  • 1
  • 10
  • 22
  • Although not strictly true - as Swift can and has to participate in Objective-C method dispatch mechanisms, to use UIKit for e.g. (and therefore has #selector), the answer has helped me realise that I don't need the wrapping `if` at all if I use optional chaining: `userDelegate?.scrollViewDidScroll?(scrollView)`. It solves my issue, but I suppose wouldn't solve other use cases.. Thanks for the answer! – Alexandre G Dec 10 '16 at 08:51