ios swift reflection performselector swift2.2

ios - ¿Cómo invocar un método de clase usando performSelector() en AnyClass en Swift?



reflection swift2.2 (2)

Si desea realizar el cálculo en la máquina, solo haga lo siguiente:

Machine.calculate(NSNumber(integer: 1337))

Si necesita llamar al selector de ejecución, haga lo siguiente:

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) }

En ObjC, simplemente podría invocar un método de clase utilizando el método de clase de NSObject .

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

¿Pero cómo haces esto en 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) }

Con este código recibo el siguiente error de compilación:

error: no se puede invocar ''performSelector'' con una lista de argumentos de tipo ''(Selector, withObject: NSNumber)''

¿Que me estoy perdiendo aqui?


AnyClass no se ajusta a NSObjectProtocol fuera de la caja. Tuve que lanzar aClass como NSObjectProtocol para usar performSelector ( performSelector:withObject: está performSelector:withObject: a Swift como un método en 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)

Un poco más seguro:

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 devuelve un objeto no Unmanaged , por eso takeUnretainedValue() (u opcionalmente takeRetainedValue() si desea transferir la propiedad de la memoria) son necesarios.