2015-06-16 5 views
11

मुझे आश्चर्य है कि id पर एक विधि को कॉल करने में स्विफ्ट समकक्ष क्या है जिसमें विधि की उपलब्धता रनटाइम पर निर्धारित की जाती है। विशेष रूप से मैं स्विफ्ट में इस पैटर्न करने के लिए देख रहा हूँ:`आईडी` पर गुणों को सेट करने के लिए तेज़ समतुल्य क्या है?

-(IBAction) handleEvent:(id) sender { 
    BOOL didDisable = NO; 
    if([sender respondsToSelector:@selector(setEnabled:)]) { 
     [sender setEnabled:NO]; 
     didDisable = YES; 
    } 
    [self doSomethingAsyncWithCompletionHandler:^{ 
     if(didDisable) { 
      [sender setEnabled:YES]; 
     } 
    }]; 
} 

सबसे बड़ी समस्या यह है कि setEnabled: (जैसे UIBarItem) एक संपत्ति के रूप में स्विफ्ट में आयात किया जाता है और निम्नलिखित निर्माणों में से कोई भी संकलन

func handleEvent(sender: AnyObject) { 
    // Error: AnyObject does not have a member named "enabled" 
    sender.enabled? = false 

    // Error: (BooleanLiteralCompatible) -> _ is not identical to Bool 
    sender.setEnabled?(false) 
} 
+1

यदि संभव हो, प्रोटोकॉल का उपयोग करके इस कार्यक्षमता को लागू करें। फिर आप 'ifs let' चयनकर्ता को 'if-let'' के साथ बदल सकते हैं, जैसे कि अगर toggable = प्रेषक के रूप में? Toggable' ('सक्षम' प्रॉपर्टी के साथ 'प्रोटोकॉल Toggable' मानते हुए)। – dcestari

+0

यकीन नहीं है, लेकिन शायद AnyObject? – kostek

+0

http://roadfiresoftware.com/2014/07/swifts-var-is-not-objective-cs-id/ –

उत्तर

6

स्विफ्ट 2 में।0 बीटा 4, आपकी प्रार्थनाओं का उत्तर दिया जाता है; इस कोड को कानूनी हो जाता है:

@IBAction 
func handleEvent(sender: AnyObject) { 
    if sender.respondsToSelector("setHidden:") { 
     sender.performSelector("setHidden:", withObject: true) 
    } 
} 
+0

विचित्र रूप से, मैं इसे 'setEnabled' के लिए कुछ भी नहीं कर सकता: '(यह संकलित करता है लेकिन बटन अक्षम नहीं होता है)। हालांकि, यह एक अस्थायी बग हो सकता है; चूंकि यह 'छुपा' के लिए काम करता है, मुझे लगता है कि हमें लगता है कि इसे 'सक्षम' के लिए काम करना चाहिए। – matt

+1

मैंने 'प्रदर्शन चयनकर्ता (" setEnabled: ") 'मुद्दे पर एक बग दायर किया। यह क्रैश नहीं होता है लेकिन न ही यह _do_ कुछ भी करता है। – matt

+0

मैं इसे 'setEnabled:' के साथ काम करने में सक्षम था, लेकिन एक अजीब तरीके से ... '.performSelector (" setEnabled: ") 'हमेशा ** सत्य ** और' .performSelector (" setEnabled: ", withObject: nil)' हमेशा के साथ सक्षम है ** झूठी **, 'OOject: 'के मान के बावजूद। मुझे लगता है कि वास्तव में एक बग दर्ज करने के लायक ... –

24

है वास्तव में आप इसे वैसे ही कर सकते हैं जैसा आप पहले कर रहे थे: respondsToSelector: पर कॉल करके। दरअसल, कि वास्तव में क्या अपने प्रस्तावित अभिव्यक्ति करता है:

sender.setEnabled?(false) 

अभिव्यक्ति वास्तव में एक आशुलिपि है कि - यह respondsToSelector: पहले कहता है, और फिर कॉल setEnabled: केवल तभी respondsToSelector: परीक्षण गुजरता है। दुर्भाग्यवश, जैसा कि आप कहते हैं, आप उस कोड को संकलित करने के लिए नहीं प्राप्त कर सकते हैं। हालांकि, यह उपलब्ध विधियों के स्विफ्ट के ज्ञात रिपर्टरी का केवल एक कर्कश है। तथ्य यह है कि, हालांकि इसे संकलित करने के लिए थोड़ा मुश्किल है, लेकिन यह किया जा सकता है - और एक बार जब आप इसे संकलित कर लेते हैं, तो यह वैसे ही व्यवहार करता है जैसा आप उम्मीद करेंगे।

हालांकि, मैं इसे संकलित करने के लिए कैसे समझाऊंगा, क्योंकि मैं इस तरह की चालबाजी को प्रोत्साहित नहीं करना चाहता हूं। इस प्रकार की गतिशील संदेश स्विफ्ट में निराश है। सामान्य रूप से, स्विफ्ट में कुंजी-मूल्य कोडिंग, आत्मनिरीक्षण, और आगे की गतिशील संदेश चाल की आवश्यकता नहीं होती है और स्विफ्ट के मजबूत टाइपिंग दृष्टिकोण के साथ व्यंजन नहीं होती है। चीजों को स्विफ्ट तरीके से करना बेहतर होगा, वैकल्पिक रूप से कुछ ऐसा करने के लिए जो आपके पास यह मानने का कारण हो और यह enabled संपत्ति हो।

@IBAction func doButton(sender: AnyObject) { 
    switch sender { 
    case let c as UIControl: c.enabled = false 
    case let b as UIBarItem: b.enabled = false 
    default:break 
    } 
} 

या: उदाहरण के लिए:

@IBAction func doButton(sender: AnyObject) { 
    (sender as? UIControl)?.enabled = false 
    (sender as? UIBarItem)?.enabled = false 
} 
+2

गंध कोड को प्रोत्साहित करने के लिए अंगूठे नहीं –

+0

तो क्या आप मुझे बता रहे हैं कि उदाहरण कम गंध है? –

+0

"... गतिशील संदेश स्विफ्ट में निराश है ..." जबकि शेष कोको इसका भारी उपयोग करता है। यदि यह मामला है तो मैं उद्देश्य-सी पर चिपके रहूंगा। – adib

2

आप respondsToSelector: विधि का उपयोग कर से बचने के लिए चाहते हैं तो आप के बजाय एक प्रोटोकॉल को परिभाषित कर सकते हैं। फिर उन वर्गों का विस्तार करें जिन्हें आप उपयोग करना चाहते हैं जो पहले से ही इस प्रोटोकॉल की परिभाषा के अनुरूप है (सक्षम) और फ़ंक्शन को अपने प्रोटोकॉल के अनुरूप एक सामान्य चर के साथ परिभाषित करें।

protocol Enablable{ 
    var enabled:Bool { get set } 
} 

extension UIButton  : Enablable {} 
extension UIBarButtonItem : Enablable {} 

//.... 

func handleEvent<T:Enablable>(var sender: T) { 
    sender.enabled = false 
} 

आप एक IBAction विधि के बाद से आप उन पर सीधे जेनरिक उपयोग नहीं कर सकते एक काम का एक छोटा सा के आसपास की आवश्यकता है के साथ इसका इस्तेमाल करने की जरूरत है।

@IBAction func handleEventPressed(sender:AnyObject){ 
    handleEvent(sender); 
} 

हम भी ताकि हम जानते हुए भी मौसम या नहीं इस के बिना handleEvent कॉल कर सकते हैं Enablable है Enablable अनुरूपता के बिना एक मिलान सामान्य समारोह की जरूरत है। सौभाग्य से कंपाइलर यह समझने के लिए पर्याप्त स्मार्ट है कि उपयोग करने के लिए दो सामान्य कार्यों में से कौन सा है।

func handleEvent<T>(var sender: T) { 
    //Do Nothing case if T does not conform to Enablable 
} 
1

एक समाधान/विकल्प के रूप में, आप मुख्य मान कोडिंग उपयोग कर सकते हैं:

@IBAction func handler(sender: AnyObject) { 

    if sender.respondsToSelector("setEnabled:") { 
     sender.setValue(false, forKey:"enabled") 
    } 
} 

यह दोनों स्विफ्ट 1.2 (Xcode 6.4) और स्विफ्ट 2.0 (Xcode के साथ काम करता 7 बीटा)।

संबंधित मुद्दे