Swift 中#function 和#selector 的不同结果

Different result from #function and #selector in Swift

我试图检测是否在 Swift 中使用 #function 调用了一个方法,但结果 returns 与 #selector 的描述不同。这是一个工作代码:

class SampleClass {

    var latestMethodCall: Selector?

    @objc func firstMethod() {
        latestMethodCall = #function
    }

    @objc func secondMethod(someParameters: Int, anotherParameter: Int) {
        latestMethodCall = #function
    }

    func isEqualToLatestMethod(anotherMethod anotherMethod: Selector) -> Bool {
        return latestMethodCall?.description == anotherMethod.description
    }
}


let sampleObject = SampleClass()

sampleObject.firstMethod()

let expectedFirstMethod = #selector(SampleClass.firstMethod)

if sampleObject.isEqualToLatestMethod(anotherMethod: expectedFirstMethod) {

    print("Working correctly!")

} else {

    print("Broken selector...")

    if let latestMethodCall = sampleObject.latestMethodCall {
        print("Object's latest method call: \(latestMethodCall.description)") // prints firstMethod()
        print("Expected method call: \(expectedFirstMethod.description)") // prints firstMethod
    }
}

sampleObject.secondMethod(5, anotherParameter: 7)

let expectedSecondMethod = #selector(SampleClass.secondMethod(_:anotherParameter:))

if sampleObject.isEqualToLatestMethod(anotherMethod: expectedSecondMethod) {

    print("Working correctly!")

} else {

    print("Broken selector...")

    if let latestMethodCall = sampleObject.latestMethodCall {
        print("Object's latest method call: \(latestMethodCall.description)") // prints secondMethod(_:anotherParameter:)
        print("Expected method call: \(expectedSecondMethod.description)") // prints secondMethod:anotherParameter:
    }
}

从上面的示例中,我发现 #function returns Swift-y 描述,而 #selector returns ObjC-y 描述。这是预期的吗?还是我做错了什么?

感谢您抽出宝贵时间! :)

在Swift < 3.0 Selector 类型可以通过String 初始化。由于这样做是不安全的(这种方法来自动态 Objective-C),#selector 在 Swift 2.2 中引入。 #selector 将不允许您为不存在的方法定义 Selector

现在,让我们更深入地了解如何通过字符串初始化 Selector。选择器的字符串应该有严格的特殊签名:对于没有参数的方法 func firstMethod() 它只是没有大括号的方法名称:"firstMethod"。另一方面,#function 关键字绝对不是用于定义 Selector 的,它是 return 带有大括号的函数标签:

@objc func firstMethod() {
    print(#function)
}
//firstMethod()

如果您将定义带有参数的方法,您会看到 #function 现在将 return 相同但没有大括号

@objc func firstMethod(param: Int) {
    print(#function)
}
//firstMethod

因为 Selector,再次期待它的其他签名:"firstMethod:".

结论:定义Selector使用#selector;在 Swift >= 3.0 中你将别无选择。