2017-02-13 6 views
8

मैं निम्नलिखित समारोह जहाँ मैं पूरा होने हैंडलर है, लेकिन मैं इस त्रुटि मिल रही है की अनुमति दे सकतास्विफ्ट 3:</p> <pre><code>Closure use of non-escaping parameter may allow it to escape </code></pre> <p>यहाँ मेरी कोड है:: गैर बचने पैरामीटर के बंद उपयोग यह बचने के लिए

func makeRequestcompletion(completion:(_ response:Data, _ error:NSError)->Void) { 
    let urlString = URL(string: "http://someUrl.com") 
    if let url = urlString { 
     let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, urlRequestResponse, error) in 
      completion(data, error) // <-- here is I'm getting the error 
     }) 
    task.resume() 
    } 
} 

enter image description here आप में से कोई भी जानता है कि मुझे यह त्रुटि क्यों मिल रही है?

मैं सच में तुम्हारी मदद

+0

इसका संदर्भ लें [गैर-भागने वाले पैरामीटर का क्लोजर उपयोग इसे से बचने की अनुमति दे सकता है] (https://stackoverflow.com/q/38990882/6521116) –

उत्तर

8

ऐसा लगता है कि स्पष्ट रूप से परिभाषित करने के लिए है कि बंद करने से बचने के लिए अनुमति दी है की जरूरत सराहना करेंगे।

Apple Developer docs से,

A closure is said to escape a function when the closure is passed as an argument to the function, but is called after the function returns. When you declare a function that takes a closure as one of its parameters, you can write @escaping before the parameter’s type to indicate that the closure is allowed to escape.

TLDR; पूरा होने के बाद चर @escaping कीवर्ड जोड़ें:

func makeRequestcompletion(completion: @escaping (_ response:Data, _ error:NSError)->Void) { 
    let urlString = URL(string: "http://someUrl.com") 
    if let url = urlString { 
     let task = URLSession.shared.dataTask(with: url, completionHandler: { (data, urlRequestResponse, error) in 
      completion(data, error) // <-- here is I'm getting the error 
     }) 
     task.resume() 
    } 
} 
+0

@escaping क्यों पूछ रहा है? – user2924482

+3

अब स्विफ्ट 3 में आपको स्पष्ट रूप से परिभाषित करना होगा जब किसी फ़ंक्शन में एक समापन हैंडलर होता है जो फ़ंक्शन के बाद निष्पादित होता है (भागना)। ऐप्पल कहता है, "ऑपरेशन शुरू होने के बाद फ़ंक्शन वापस आता है, लेकिन ऑपरेशन पूरा होने तक बंद नहीं किया जाता है-बंद करने के लिए बाद में बुलाया जाना बंद कर देता है। ... यदि आपने इसका पैरामीटर चिह्नित नहीं किया है @escaping के साथ काम करें, आपको एक संकलन-समय त्रुटि मिल जाएगी। " –

+0

बस स्पष्टीकरण के लिए @ मार्कबार्सो को धन्यवाद देने के लिए छोड़कर। पढ़ा गया था लेकिन पूरी "बचने वाली चीज़" को समझ नहीं पाया, और इस टिप्पणी ने मुझे प्रकाश देखा;) –

3

एक "से बचने" बंद को बंद करने कि गुंजाइश है कि यह में बनाया गया था से अधिक जीवित कर सकते हैं पलायन बंद संदर्भ गिनती और स्मृति प्रबंधन के आसपास विशेष देखभाल की आवश्यकता है और कठिन हो सकता है। अनुकूलन करने के लिए।

स्विफ्ट 3 से पहले, बंद करने के लिए डिफ़ॉल्ट यह मानना ​​था कि वे भाग रहे थे। इसका मतलब यह था कि डेवलपर्स को विशेष रूप से क्लोजर को अनुकूलन करने की अनुमति देने के लिए ज्ञात बंद करने की पहचान नहीं की गई थी। समुदाय ने पाया कि वास्तव में, अगर क्लोजर बच रहा है या नहीं, तो संकलक आसानी से पता लगा सकता है, और निर्णय लिया कि बचने के लिए आक्रामक दृष्टिकोण के परिणामस्वरूप तेजी से कोड हो सकता है। नतीजा यह है कि बंद होने को अब गैर-भागने के लिए माना जाता है, और आपको @escaping विशेषता से बचने वाले बंद करने की आवश्यकता है।

आपके मामले में, URLSession.shared.dataTask स्वीकार करने का बंद होना ही एक भागने वाला बंद है, इसलिए यदि आप इसके अंदर एक बंद करने का उपयोग करते हैं, तो इसे @escaping चिह्नित करने की भी आवश्यकता है।

+0

ठीक करने के तरीके का एक कोड उदाहरण बहुत अच्छा होगा। – Linasses

+0

@ लीनास की समाप्ति: @ सेस्केपिंग (_ प्रतिक्रिया: डेटा, _ त्रुटि: एनएसईआरआरआर) -> शून्य '। – zneak

+1

'एस्केपिंग' त्रुटि पॉप-अप हालांकि मेरे पास पहले से ही '@ escaping' है: | खुला स्थैतिक func resume सत्र (_ समापन: @escaping (परिणाम <सत्र, त्रुटि>) -> (शून्य)) {@ त्रुटि से बचने में त्रुटि पॉप अप हालांकि मैं पहले से ही @ escaping है: | खुला स्थैतिक func resume सत्र (_ समापन: @ भागना (परिणाम <सत्र, त्रुटि>) -> (शून्य)) { –

0

@escaping सभी कॉलिंग विधियों के लिए संक्रामक है, और संकलक निर्धारित करता है कि में यह शामिल होना चाहिए।

इस उदाहरण पर विचार (जो संकलित):

dispatchSometime({ print("Oh yeah") }) 

func dispatchSometime(_ block:()->()) { 
    dispatchNow(block) 
} 

func dispatchNow(_ block:()->()) { 
    block() 
} 

यह संशोधित उदाहरण है, तथापि, प्रकार non-escaping parameter may allow it to escape की दो त्रुटियों का उत्पादन:

dispatchSometime({ print("Oh yeah") }) 

func dispatchSometime(_ block:()->()) { 
    dispatchLater(block) 
} 

func dispatchLater(_ block:()->()) { 
    DispatchQueue.main.async(execute: block) 
} 

मुख्य पर प्रेषण का मतलब है dispatchLater विधि की जरूरत है @escaping, और एक बार जब आप इसे जोड़ देते हैं, तो dispatchSometime विधि भीकी आवश्यकता है संकलन के उदाहरण के लिए।

dispatchSometime({ print("Oh yeah") }) 

func dispatchSometime(_ block: @escaping()->()) { 
    dispatchLater(block) 
} 

func dispatchLater(_ block: @escaping()->()) { 
    DispatchQueue.main.async(execute: block) 
} 

हालांकि, दूर ले बस है:

  • रखें जब तक संकलक शिकायत करना बंद कर देता @escaping अप कॉल श्रृंखला जोड़ने।
  • कीवर्ड कुछ भी नहीं बदलेगा: यह एक चेतावनी है जो कहती है, अनिवार्य रूप से, "weak का उपयोग कैप्चर वैरिएबल के साथ करने के लिए सावधान रहें क्योंकि उन्हें ब्लॉक के साथ ही बनाए रखा जा सकता है।"

निहितार्थ

इस के साथ वास्तव में मज़ा मामले आप @escaping कीवर्ड है, जो शिकायत करना बंद करो करने के लिए संकलक हो जाता है शामिल करने के लिए कई तरीके समायोजित करना जहां है। हालांकि, यदि वे विधियां वास्तव में प्रोटोकॉल के अनुरूप होती हैं, तो प्रोटोकॉल के तरीकों को भी@escaping कीवर्ड प्राप्त करें, जो अन्य सभी प्रोटोकॉल अनुरूपों को भी संक्रमित करता है। मज़ा!

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