2015-02-10 16 views
75

कार्यों में बंद मानकों के साथ स्विफ्ट 1.2 में एक नई विशेषता है, और प्रलेखन के रूप में कहते हैं:@noescape विशेषता 1.2

यह बताता है कि पैरामीटर ही कभी कहा जाता है (या एक के रूप में पारित @ एक कॉल में noescape पैरामीटर), जिसका अर्थ है कि यह कॉल के जीवनकाल से अधिक जीवित नहीं कर सकते हैं।

मेरी समझ में, हम [weak self] का उपयोग कर सकते हैं ताकि बंद करने के लिए एक मजबूत संदर्भ न हो। अपने वर्ग, और स्वयं शून्य हो सकता है या उदाहरण है जब बंद निष्पादित किया जाता है, लेकिन अब, @noescape मतलब यह है कि बंद करता है, तो वर्ग deinitalized है कभी नहीं निष्पादित किया जाएगा। क्या मैं इसे सही ढंग से समझता हूँ?

और यदि मैं सही हूं, तो मैं नियमित कार्य के @noescape बंद होने का उपयोग क्यों करूंगा, जब वे बहुत समान व्यवहार करते हैं?

उत्तर

143

@noescape इस तरह इस्तेमाल किया जा सकता:

func doIt(code: @noescape() ->()) { 
    /* what we CAN */ 

    // just call it 
    code() 
    // pass it to another function as another `@noescape` parameter 
    doItMore(code) 
    // capture it in another `@noescape` closure 
    doItMore { 
     code() 
    } 

    /* what we CANNOT do ***** 

    // pass it as a non-`@noescape` parameter 
    dispatch_async(dispatch_get_main_queue(), code) 
    // store it 
    let _code:() ->() = code 
    // capture it in another non-`@noescape` closure 
    let __code = { code() } 

    */ 
} 

func doItMore(code: @noescape() ->()) {} 

@noescape की गारंटी देता है जोड़ा जा रहा है कि बंद कहीं संग्रहीत नहीं किया जाएगा, बाद में इस्तेमाल किया, या असमकालिक इस्तेमाल किया।

कॉलर के दृष्टिकोण से, कैप्चर किए गए चर के जीवनकाल की परवाह करने की कोई आवश्यकता नहीं है, क्योंकि इन्हें बुलाए गए फ़ंक्शन के भीतर उपयोग किया जाता है या नहीं। और बोनस के रूप में, हम self. टाइप करने से हमें बचाने के लिए एक अंतर्निहित self का उपयोग कर सकते हैं।

func doIt(code: @noescape() ->()) { 
    code() 
} 

class Bar { 
    var i = 0 
    func some() { 
     doIt { 
      println(i) 
      // ^we don't need `self.` anymore! 
     } 
    } 
} 

let bar = Bar() 
bar.some() // -> outputs 0 

इसके अलावा, देखने के संकलक के बिंदु (release notes में दस्तावेज के रूप में) से:

यह कुछ मामूली प्रदर्शन अनुकूलन सक्षम बनाता है।

+5

मेरे लिए महत्वपूर्ण बिट: "' @ नोस्केप 'गारंटी देता है कि बंद नहीं होगा ... अतुल्यकालिक रूप से उपयोग किया जाएगा "। जिसका अर्थ है कि आप इसे नेटवर्किंग कोड के साथ उपयोग नहीं कर सकते हैं जो एसिंक को निकाल देता है। –

28

इसके बारे में सोचने का एक तरीका यह है कि @noescape ब्लॉक के अंदर प्रत्येक चर को मजबूत (केवल स्वयं नहीं) की आवश्यकता नहीं है।

भी संभव अनुकूलन के बाद से एक बार एक चर आवंटित किया जाता है कि उसके बाद एक ब्लॉक में लिपटे, यह सिर्फ सामान्य रूप से समारोह के अंत में पुनः आवंटित की जाती नहीं किया जा सकता हैं। तो इसे ढेर पर आवंटित किया जाना चाहिए और डीआरओस्ट्रक्चर करने के लिए एआरसी का उपयोग करना चाहिए। उद्देश्य-सी में, आपको यह सुनिश्चित करने के लिए "__block" कीवर्ड का उपयोग करना होगा कि चर को ब्लॉक अनुकूल तरीके से बनाया गया है। स्विफ्ट स्वचालित रूप से इसका पता लगाएगा ताकि कीवर्ड की आवश्यकता न हो, लेकिन लागत एक जैसी है।

चर एक @nosecape ब्लॉक करने के लिए पारित किया जा रहा रहे हैं, तो वे चर ढेर किया जा सकता है, और पुनःआवंटन लिए एआरसी जरूरत नहीं है।

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

यह सब तेजी से और अधिक इष्टतम कोड का परिणाम है। और @autoclosure ब्लॉक (जो बहुत उपयोगी हैं) का उपयोग करने के लिए ओवरहेड को कम कर देता है।

+0

क्या आप कुछ संदर्भ दे सकते हैं जहां मैंने यहां बताया है, मैं इन विवरणों में वास्तव में रूचि रखूंगा। –

+0

नीचे मेरा जवाब देखें। –

8

(ऊपर माइकल ग्रे की जवाब के संदर्भ में।)

यह सुनिश्चित नहीं है कि यह विशेष रूप से स्विफ्ट के लिए प्रलेखित है, या यदि स्विफ्ट कंपाइलर भी इसका पूरा लाभ लेता है। लेकिन यह मानक कंपाइलर डिज़ाइन स्टैक पर एक उदाहरण के लिए स्टोरेज आवंटित करने के लिए है यदि संकलक जानता है कि फ़ंक्शन कहा जा रहा है, तो उस उदाहरण में उस पॉइंटर को ढेर में स्टोर करने का प्रयास नहीं करेगा, और यदि फ़ंक्शन ऐसा करने का प्रयास करता है तो संकलन-समय त्रुटि जारी करें ।

यह गैर-स्केलर मान प्रकारों (जैसे enums, structs, closures) को पार करते समय विशेष रूप से फायदेमंद है क्योंकि उन्हें कॉपी करना संभवतः स्टैक पर पॉइंटर पास करने से कहीं अधिक महंगा है। उदाहरण आवंटित करना भी काफी महंगा है (एक निर्देश बनाम मॉलोक())। तो यह एक डबल-जीत है यदि संकलक इस अनुकूलन को कर सकता है।

फिर से, स्विफ्ट कंपाइलर का दिया गया संस्करण वास्तव में स्विफ्ट टीम द्वारा कहा जाना चाहिए या नहीं, या जब आप इसे खोलने के स्रोत स्रोत को पढ़ना होगा। "मामूली अनुकूलन" के बारे में उद्धरण से, ऐसा लगता है कि यह या तो नहीं है, या स्विफ्ट टीम इसे "मामूली" मानती है। मैं इसे एक महत्वपूर्ण अनुकूलन मानता हूं।

संभवतः विशेषता है कि (कम से कम भविष्य में) संकलक इस अनुकूलन को करने में सक्षम हो जाएगा।

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