0

NSObject 'responds' method seems to be broken on the latest version of Xcode 9 Beta 4, Swift version 4.0.

Below is an example code tested on Xcode 8 (works fine), on Xcode 9 the method 'responds' returns false for all situations.

Any help would be appreciated.

public class Worker : NSObject
{
    public func work() { }
    public func eat(_ food: AnyObject) { }
    public func sleep(_ hours: Int,_ minutes: Int) { }
}

let worker = Worker()

let canWork = worker.responds(to: Selector(("work")))   // true
let canEat = worker.responds(to: Selector(("eat:")))    // true
let canSleep = worker.responds(to: Selector(("sleep:minutes:")))    // true
let canQuit = worker.responds(to: Selector(("quit")))   // false

Example source : https://stackoverflow.com/a/24168825

vacawama
  • 150,663
  • 30
  • 266
  • 294
swift.coder
  • 33
  • 1
  • 7
  • Related: https://stackoverflow.com/questions/44390378/how-can-i-deal-with-objc-inference-deprecation-with-selector-in-swift-4 – Martin R Jul 28 '17 at 11:09
  • 1
    Xcode 9 should suggest the modern `#selector(Worker.work)` syntax. And once you use that, the compiler warns: *"argument of '#selector' refers to instance method 'work()' in 'Worker' that depends on '@objc' inference deprecated in Swift 4"* – Martin R Jul 28 '17 at 11:15
  • @MartinR, I was going to suggest that OP use `#selector` syntax, but then `#selector(quit)` doesn't even compile which negates the ability to do a runtime check. – vacawama Jul 28 '17 at 11:25
  • @vacawama: You are right. – Martin R Jul 28 '17 at 11:37

1 Answers1

3

There's nothing wrong with the responds method. Due to SE-0160 which is implemented in Swift 4, these methods are no longer automatically exposed to Objective-C.

If you add @objc to the start of each method signature (that you want to expose to Objective-C), you will find that responds then returns true.

public class Worker : NSObject
{
    @objc public func work() { }
    @objc public func eat(_ food: AnyObject) { }
    @objc public func sleep(_ hours: Int,_ minutes: Int) { }
}

Alternatively, you can also add @objMembers to the class to expose all of the methods to Objective-C.

@objMembers
public class Worker : NSObject
{
    public func work() { }
    public func eat(_ food: AnyObject) { }
    public func sleep(_ hours: Int,_ minutes: Int) { }
}

Your third Selector syntax is wrong. It should be "sleep::" because the minutes label is not used due to the preceding _.

vacawama
  • 150,663
  • 30
  • 266
  • 294