如何在 Swift 中的 AnyClass 上使用 performSelector() 调用 class 方法?
How to invoke a class method using performSelector() on AnyClass in Swift?
在 ObjC 中,您可以使用 NSObject
中的 class 方法简单地调用 class 方法。
[Machine performSelector:@selector(calculate:) withObject:num];
但是在 Swift 2.2 中如何做到这一点?
@objc(Machine) // put it here, so you can simply copy/paste into Playground
class Machine: NSObject {
static func calculate(param: NSNumber) -> String {
if param.integerValue > 5 {
return "42"
}
return "42" // there is only 1 answer to all the questions :D
}
}
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
let answer = aClass.performSelector(sel, withObject: num) // compiler error
// let answer = aClass.calculate(num) // <-- this works
print(answer)
}
使用此代码,我收到以下编译器错误:
error: cannot invoke 'performSelector' with an argument list of type '(Selector, withObject: NSNumber)'
我在这里错过了什么?
如果您想在机器上执行计算,只需执行:
Machine.calculate(NSNumber(integer: 1337))
如果需要调用perform selector,则:
if let aClass = NSClassFromString("Machine") as? AnyObject
{
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
let answer = aClass.performSelector(sel, withObject: num)
print(answer)
}
AnyClass
不符合开箱即用的NSObjectProtocol
。我必须将 aClass
转换为 NSObjectProtocol
才能使用 performSelector
(performSelector:withObject:
作为 NSObjectProtocol
上的方法桥接到 Swift):
Swift 3:
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(param:))
let num = NSNumber(value: 1337)
if let myClass = aClass as? NSObjectProtocol {
if myClass.responds(to: sel) {
let answer = myClass.perform(sel, with: num).takeRetainedValue() // this returns AnyObject, you may want to downcast to your desired type
print(answer) // "42\n"
}
}
}
Swift 2.x:
(aClass as! NSObjectProtocol).performSelector(sel, withObject: num) // Unmanaged<AnyObject>(_value: 42)
安全一点:
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
if let myClass = aClass as? NSObjectProtocol {
if myClass.respondsToSelector(sel) {
let answer = myClass.performSelector(sel, withObject: num).takeUnretainedValue()
print(answer) // "42\n"
}
}
}
performSelector
returns 一个 Unmanaged
对象,这就是为什么需要 takeUnretainedValue()
(或者如果你想转移内存所有权,则可以选择 takeRetainedValue()
)。
在 ObjC 中,您可以使用 NSObject
中的 class 方法简单地调用 class 方法。
[Machine performSelector:@selector(calculate:) withObject:num];
但是在 Swift 2.2 中如何做到这一点?
@objc(Machine) // put it here, so you can simply copy/paste into Playground
class Machine: NSObject {
static func calculate(param: NSNumber) -> String {
if param.integerValue > 5 {
return "42"
}
return "42" // there is only 1 answer to all the questions :D
}
}
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
let answer = aClass.performSelector(sel, withObject: num) // compiler error
// let answer = aClass.calculate(num) // <-- this works
print(answer)
}
使用此代码,我收到以下编译器错误:
error: cannot invoke 'performSelector' with an argument list of type '(Selector, withObject: NSNumber)'
我在这里错过了什么?
如果您想在机器上执行计算,只需执行:
Machine.calculate(NSNumber(integer: 1337))
如果需要调用perform selector,则:
if let aClass = NSClassFromString("Machine") as? AnyObject
{
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
let answer = aClass.performSelector(sel, withObject: num)
print(answer)
}
AnyClass
不符合开箱即用的NSObjectProtocol
。我必须将 aClass
转换为 NSObjectProtocol
才能使用 performSelector
(performSelector:withObject:
作为 NSObjectProtocol
上的方法桥接到 Swift):
Swift 3:
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(param:))
let num = NSNumber(value: 1337)
if let myClass = aClass as? NSObjectProtocol {
if myClass.responds(to: sel) {
let answer = myClass.perform(sel, with: num).takeRetainedValue() // this returns AnyObject, you may want to downcast to your desired type
print(answer) // "42\n"
}
}
}
Swift 2.x:
(aClass as! NSObjectProtocol).performSelector(sel, withObject: num) // Unmanaged<AnyObject>(_value: 42)
安全一点:
if let aClass = NSClassFromString("Machine") {
let sel = #selector(Machine.calculate(_:))
let num = NSNumber(integer: 1337)
if let myClass = aClass as? NSObjectProtocol {
if myClass.respondsToSelector(sel) {
let answer = myClass.performSelector(sel, withObject: num).takeUnretainedValue()
print(answer) // "42\n"
}
}
}
performSelector
returns 一个 Unmanaged
对象,这就是为什么需要 takeUnretainedValue()
(或者如果你想转移内存所有权,则可以选择 takeRetainedValue()
)。