2011-09-14 9 views
29

NSData हमेशा +dataWithContentsOfURL:options:error: नामक एक बहुत ही सुविधाजनक विधि है। सुविधाजनक होने पर, यह वर्तमान धागे के निष्पादन को भी अवरुद्ध करता है, जिसका अर्थ है कि यह मूल रूप से उत्पादन कोड के लिए बेकार था (NSOperation को अनदेखा कर रहा था)। मैंने इस विधि को इतनी बार प्रयोग किया, मैं पूरी तरह से भूल गया कि यह अस्तित्व में है। हाल ही तक।NSURLConnection बनाम NSData + GCD

तरह से मैं नलियों से डेटा हथियाने किया गया है मानक NSURLConnectionDelegate दृष्टिकोण है: एक डाउनलोड वर्ग है कि विभिन्न NSURLConnectionDelegate तरीकों संभालती लिखें कुछ डेटा का निर्माण धीरे-धीरे,, त्रुटियों संभाल, आदि मैं आमतौर पर यह सामान्य बना देंगे जितना संभव हो उतने अनुरोधों के लिए पुन: उपयोग किया जा सकता है।

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

अब, ग्रांड सेंट्रल डिस्पैच दर्ज करें, और मैं के रूप में सनक से के रूप में सरल कुछ कर सकते हैं:

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 

    NSData* data = [NSData dataWithContentsOfURL:someURL]; 
    // Process data, also async... 

    dispatch_async(dispatch_get_main_queue(), ^(void) { 
     // Back to the main thread for UI updates, etc. 
    }); 
}); 

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

इस प्रकार, मेरे सवाल: वहाँ NSURLConnection (यह मानते हुए मैं डाउनलोड प्रगति की तरह चीजों के बारे में परवाह नहीं है) के बजाय सरल डेटा डाउनलोड कार्यों के लिए NSData + GCD का उपयोग कर के लिए किसी भी चेतावनियां हैं?

+2

एक के लिए अनुरोध रद्द नहीं कर सकता .. – Daniel

उत्तर

22

आप यहाँ कार्यक्षमता का एक बहुत खो रहे हैं:

  • डाउनलोड प्रगति का पालन नहीं कर सकते
  • डाउनलोड रद्द नहीं कर सकते
  • का प्रबंधन नहीं कर सकते संभव प्रमाणीकरण प्रक्रिया
  • आप आसानी से त्रुटियों को संभाल नहीं सकते हैं, जो वास्तव में महत्वपूर्ण है विशेष रूप से मोबाइल विकास जैसे आईफोन पर (क्योंकि आप अक्सर वास्तविक परिस्थितियों में अपना नेटवर्क खो देते हैं, इसलिए ऐसे नेटवर्क एरो को ट्रैक करना बहुत महत्वपूर्ण है आईओएस के लिए विकास करते समय आर मामले)

और शायद मुझे लगता है कि अधिक है।


इसके लिए सही दृष्टिकोण डाउनलोड को प्रबंधित करने से कक्षा बनाना है।

उदाहरण के लिए अपने खुद के OHURLLoader वर्ग है, जो सरल है देखें और मैं ब्लॉक के साथ उपयोग करने के लिए आसान होने के लिए एपीआई बनाया:

NSURL* url = ... 
NSURLRequest* req = [NSURLRequest requestWithURL:url]; 

OHURLLoader* loader = [OHURLLoader URLLoaderWithRequest:req]; 
[loader startRequestWithCompletion:^(NSData* receivedData, NSInteger httpStatusCode) { 
    NSLog(@"Download of %@ done (statusCode:%d)",url,httpStatusCode); 
    if (httpStatusCode == 200) { 
     NSLog(%@"Received string: %@", loader.receivedString); // receivedString is a commodity getter that interpret receivedData using the TextEncoding specified in the HTTP response 
    } else { 
     NSLog(@"HTTP Status code: %d",httpStatusCode); // Log unexpected status code 
    } 
} errorHandler:^(NSError *error) { 
    NSLog(@"Error while downloading %@: %@",url,error); 
}]; 

अधिक जानकारी के लिए GitHub पर README file और नमूना परियोजना देखें।

इस तरह:

  • आप अभी भी NSURLConnection (और द्वारा प्रदान की अतुल्यकालिक तरीकों पर भरोसा करते हैं as the Apple's documentation says about Concurrency Programming एक API पहले से ही, अतुल्यकालिक कार्यों बनाने के बजाय एक और थ्रेडिंग टेक्नोलॉजी यदि संभव हो पर निर्भर रहने के लिए इसका इस्तेमाल करने के लिए मौजूद रहने पर)
  • आप NSURLConnection (त्रुटि हैंडलिंग, आदि)
  • के फायदे रखते हैं लेकिन आपके पास ब्लॉक सिंटैक्स के फायदे भी हैं जो प्रतिनिधि कोड का उपयोग करते समय आपके कोड को अधिक पठनीय बनाता है
+0

मैं प्रगति संकेत, रद्दीकरण और प्रमाणीकरण पर आपके साथ सहमत हूं। सभी अच्छे अंक दूसरी ओर, मुझे संभालने में त्रुटि, त्रुटि के माध्यम से संभव होने की उम्मीद होगी: विधि के लिए तर्क। यदि ऐसा नहीं है, तो यह निश्चित रूप से एक प्रमुख नकारात्मक होगा। –

+0

यदि आप 'dataWithContentsOfURL: विकल्प: त्रुटि:' का उपयोग करते हैं, तो आपको कुछ त्रुटि प्रबंधन हो सकता है, लेकिन यदि आप अपने प्रश्न में केवल अपने कोड में 'डेटाविथकंट्सऑफ्लर:' का उपयोग नहीं करते हैं। लेकिन इसके अलावा, आपके पास केवल नेटवर्क त्रुटियां होंगी, न कि HTTP त्रुटियां, न ही हेडर तक पहुंच आदि। – AliSoftware

+0

+1 ग्रेट उत्तर। अपने OHURLLoader प्यार किया, यह उपयोग करने के लिए एक असली इलाज था! – Groot

12

WWDC 2010 Session Videos:

  • WWDC 2010 सत्र 207 - iPhone OS के लिए नेटवर्क एप्लिकेशन, भाग 1
  • WWDC 2010 सत्र 208 - iPhone OS के लिए नेटवर्क एप्लिकेशन, भाग 2

व्याख्याता ने कहा

"Threads Are Evil™".

नेटवर्क प्रोग्रामिंग के लिए, रनलूप के साथ एसिंक्रोनस एपीआई का उपयोग करने की दृढ़ता से अनुशंसा की जाती है।

क्योंकि, यदि आप निम्नलिखित जैसे NSData + GCD का उपयोग करते हैं, तो यह प्रति कनेक्शन एक थ्रेड का उपयोग करता है।

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^(void) { 
    NSData* data = [NSData dataWithContentsOfURL:someURL]; 

और यह कई कनेक्शन और कई धागे का उपयोग करने की संभावना है। जीसीडी का उपयोग करना बहुत आसान है :-) फिर, कई धागे इसके ढेर के लिए बड़ी मात्रा में स्मृति खाते हैं। इस प्रकार, आप एसिंक्रोनस एपीआई का उपयोग करना बेहतर करेंगे क्योंकि अली सॉफ्टवेयर ने कहा था।

2

ओएस एक्स v10.9 और आईओएस 7 के रूप में पसंदीदा तरीका NSURLSession का उपयोग करना है। यह आपको एक अच्छा, ब्लॉक-आधारित इंटरफ़ेस और सुविधाओं को रद्द करने, निलंबित करने और पृष्ठभूमि डाउनलोड करने की सुविधा देता है।