如何在Swift的AnyClass上使用performSelector()调用类方法? [英] How to invoke a class method using performSelector() on AnyClass in Swift?

查看:815
本文介绍了如何在Swift的AnyClass上使用performSelector()调用类方法?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在ObjC中,您可以简单地使用NSObject中的类方法来调用类方法.

In ObjC you could simply invoke a class method using the class method from NSObject.

[Machine performSelector:@selector(calculate:) withObject:num];

但是您如何在Swift 2.2中做到这一点?

But how do you do this in 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)
}

使用此代码,我得到以下编译器错误:

With this code I'm getting the following compiler error:

错误:无法使用类型为'(Selector,withObject:NSNumber)'的参数列表调用'performSelector'

error: cannot invoke 'performSelector' with an argument list of type '(Selector, withObject: NSNumber)'

我在这里想念什么?

推荐答案

AnyClass不符合NSObjectProtocol的规定.我必须将aClass转换为NSObjectProtocol才能使用performSelector(performSelector:withObject:作为NSObjectProtocol上的方法桥接到Swift):

AnyClass does not conform to NSObjectProtocol out of the box. I had to cast aClass as NSObjectProtocol to use performSelector (performSelector:withObject: is bridged to Swift as a method on NSObjectProtocol):

迅速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:

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())的原因.

performSelector returns an Unmanaged object, that's why takeUnretainedValue() (or optionally takeRetainedValue() if you want to transfer memory ownership) are required.

这篇关于如何在Swift的AnyClass上使用performSelector()调用类方法?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆