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 中你将别无选择。
我试图检测是否在 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 中你将别无选择。