ios – 如何在Swift的AnyClass上使用performSelector()调用类方法?

在ObjC中,您可以使用NSObject中的类方法简单地调用方法.
[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)’

在这里错过了什么?

解决方法

AnyClass不符合开箱即用的NSObjectProtocol.我必须将aClass转换为NSObjectProtocol以使用performSelector(performSelector:withObject:作为NSObjectProtocol上的方法桥接到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返回一个Unmanaged对象,这就是为什么需要takeUnretainedValue()(或者如果你想传输内存所有权,可选择takeRetainedValue()).

相关文章

UITabBarController 是 iOS 中用于管理和显示选项卡界面的一...
UITableView的重用机制避免了频繁创建和销毁单元格的开销,使...
Objective-C中,类的实例变量(instance variables)和属性(...
从内存管理的角度来看,block可以作为方法的传入参数是因为b...
WKWebView 是 iOS 开发中用于显示网页内容的组件,它是在 iO...
OC中常用的多线程编程技术: 1. NSThread NSThread是Objecti...