ios - स्विफ्ट में AnyClass पर performSelector() का उपयोग कर एक क्लास विधि कैसे खोलें?




swift reflection (2)

यदि आप मशीन पर गणना करना चाहते हैं, तो बस करें:

Machine.calculate(NSNumber(integer: 1337))

यदि आपको चयन करने वाले को कॉल करने की आवश्यकता है, तो करें:

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

ObjC में आप NSObject से क्लास मेथड का उपयोग करके केवल एक क्लास विधि का उपयोग कर सकते थे।

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

लेकिन आप इसे स्विफ्ट 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)
}

इस कोड के साथ मुझे निम्नलिखित कंपाइलर त्रुटि मिल रही है:

त्रुटि: प्रकार की एक तर्क सूची के साथ 'performSelector' को नहीं ला सकता है '(चयनकर्ता, withObject: NSNumber)'

मुझे यहां क्या समझ नहीं आ रहा है?


AnyClass बॉक्स के बाहर NSObjectProtocol अनुरूप नहीं है। मुझे aClass का उपयोग करने के लिए NSObjectProtocol रूप में एक aClass डालना पड़ा (प्रदर्शनकर्ता performSelector:withObject: 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"
        }
    }
}

स्विफ्ट 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() लिया गया मूल्य) आवश्यक हैं





swift2.2