6

मैं प्रस्तुतियों में से कुछ पर देखा है WWDC 2010 फार्म और भी ब्लॉक और संगामिति पर दस्तावेज़ों के सबसे पढ़ सकते हैं और ग्रांड सेंट्रल डिस्पैच में धारावाहिक कतारों के साथ ब्लॉकों का उपयोग कर के बारे में सवालों की एक जोड़ी है। छवियों यूआरएल और इतने पर - मैं एक iOS 4 परियोजना एक scrollview और छवि जानकारी का एक शब्दकोश है कि है। मैं छवियों को डाउनलोड करने के लिए जीसीडी और ब्लॉक का उपयोग करना चाहता हूं और उन्हें अपने स्क्रॉलव्यू में डाल देना चाहता हूं, इस प्रकार मुख्य धागे को अवरुद्ध नहीं कर रहा हूं।आईओएस 4 GCD सवाल

for (NSDictionary* dict in images) 
{ 
    dispatch_async(image_queue, ^{ 

      NSString* urlString = [dict objectForKey:@"url"]; 
      NSURL* url = [NSURL URLWithString:urlString]; 
      NSData* imageData = [[NSData alloc] initWithContentsOfURL:url]; 
      UIImage* image = [UIImage imageWithData:imageData]; 
      UIImageView* imageView = // initialize imageView with image;  

      dispatch_async(dispatch_get_main_queue(), ^{ 
       [self.scrollView addSubview:imageView]; 
      }); 
      [imageData release]; 
     }); 
} 

मैं दो प्रश्न हैं:: मैं निम्नलिखित कोड है जो काम करने के लिए लगता है लिखा है

  1. संगामिति गाइड मैं enclosing गुंजाइश है कि गैर अदिश प्रकार के होते हैं से चर पर कब्जा नहीं करना चाहिए के अनुसार - मेरे कोड में मैं एक कब्जा करता हूं जो एक NSDictionary * वस्तु है। अगर मुझे इसे कैप्चर करने की अनुमति नहीं है, तो मुझे कोड कैसे लिखना चाहिए? क्या एक ब्लॉक केवल संलग्न क्षेत्र से भिन्न चर को कैप्चर करता है जिसका उपयोग वास्तव में किया जाता है?

  2. क्या होता है अगर मैं वर्तमान ViewController छोड़ से पहले सभी छवियों धारावाहिक प्रेषण कतार के माध्यम से लाई जाती हैं? मुझे नहीं लगता कि वे जानते हैं कि उन्हें बनाए गए व्यू कंट्रोलर चले गए हैं, तो जब वे पूरा होल्डर निष्पादित करते हैं तो क्या होता है जहां मैं मुख्य थ्रेड पर अपने स्क्रॉलव्यू में छवि दृश्य डालता हूं? क्या यह एक त्रुटि या क्या कारण है? और जब मेरा व्यू कंट्रोलर गायब हो जाता है तो मैं सीरियल कतार पर किसी भी शेष परिचालन को कैसे रद्द कर सकता हूं?

सादर,

+0

मैं इस पर कुछ सर्वोत्तम प्रथाओं को भी देखना चाहता हूं। –

उत्तर

10
  1. हालांकि यह एक तुच्छ बात है, इस समझ संगामिति गाइड में बताने के लिए कोशिश कर रहा है के लिए महत्वपूर्ण है: प्वाइंटर अदिश प्रकार हैं। तो आप जो कुछ भी चाहते हैं उसके ब्लॉक के अंदर पॉइंटर्स को कैप्चर कर सकते हैं ... लेकिन आपको उस स्मृति के जीवनकाल के बारे में पता होना चाहिए जो वे इंगित करते हैं! NSDictionary * है विशेष प्रकार का-की आईडी, और जब आप एक ब्लॉक में एक आईडी का संदर्भ, क्रम आईडी को बनाए रखना है, तो ब्लॉक कॉपी किया जाता है (() जो यह dispatch_async से होता है) और फिर इसे छोड़ दें ब्लॉक की जिम्मेदारी लेता है खुद को हटा दिया गया है। और हां, एक ब्लॉक केवल चर को कैप्चर करता है जिसे इसके संदर्भ में संदर्भित किया जाता है।

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

1

@Kaelin Colclasure: 1 प्रश्न के लिए यह अधिक संभावना बहु आवेदन में साझा राज्य के एक समस्या लगता है: अभिन्न प्रकार के लिए आप मूल्य (यह भी संकेत दिए गए पर लागू होता है जो) द्वारा एक प्रति है, लेकिन आप का उपयोग करेगा जब एक एक सूचक द्वारा संदर्भित वस्तु आप सभी (वस्तु जीवनकाल समस्या आप यहाँ उल्लेख पर बदलाव की तरह) पर ताला लगा के अभाव से संबंधित समस्याओं होगा।

अगर मैं एक GCD कतार में इस्तेमाल किया एक ब्लॉक में एक अदिश गुजरती हैं, तो ब्लॉक के अंदर मैं मूल डेटा की एक प्रतिलिपि के साथ काम कर रहा हूँ:

0

यहाँ अपने पहला बिंदु के लिए व्यावहारिक अंतर है। ब्लॉक के बाहर परिवर्तन दिखाई नहीं देंगे। (उदाहरण के लिए __block संशोधक के लिए चेतावनी हैं, लेकिन सामान्य रूप से यह सही है।)

अगर मैं, पारित कहते हैं, एक NSMutableDictionary एक ब्लॉक में, शब्दकोश में परिवर्तन ब्लॉक के बाहर दिखाई जाएगी - इस वजह से आप शब्दकोश में एक संदर्भ बनाए रखा और एक गहरी प्रतिलिपि नहीं लिया ।

किसी भी मामले में मेमोरी प्रबंधन आपके लिए किया जाता है, या तो स्केलर वैरिएबल की प्रतिलिपि बनाई जाती है या वस्तुओं को बनाए रखा जाता है।

चूंकि आप इसे शुरू करने के बाद NSDictionary की सामग्री को नहीं बदल सकते हैं, तो आप शायद पाएंगे कि ब्लॉक स्वचालित रूप से आपके लिए सही चीज करते हैं।

दूसरे बिंदु पर, स्मृति प्रबंधन बहुत अधिक स्वचालित है जब तक कि आपको एक म्यूटेबल ऑब्जेक्ट की प्रति पर काम करने की आवश्यकता न हो।

3

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

2 या 3. यह की एक maxConcurrentOperationCount मूल्य के साथ एक NSOperationQueue उपयोग करने के लिए आप नेटवर्क अनुरोधों की एक संभावित अनंत राशि कतार करने की अनुमति देगा का प्रयास करें लेकिन सबसे कुछ पर समानांतर में प्रदर्शन किया है। चूंकि आप डिवाइस की नेटवर्क स्थिति तक पहुंच सकते हैं, इसलिए आप वाईफाई कनेक्शन के लिए 8 कहने के लिए सशर्त रूप से इसे बढ़ा सकते हैं।

और जीसीडी के साथ दूसरी समस्या यह है कि लंबित परिचालनों को रद्द करने के लिए यह थोड़ा बोझिल है। यदि आपका उपयोगकर्ता दृश्य नियंत्रक में प्रवेश करता है और फिर आपके कोड को प्रोग्राम करने के तरीके के आधार पर वापस चला जाता है, तो जीसीडी ब्लॉक दृश्य नियंत्रक को बनाए रखेगा, इसे रिलीज़ होने से रोक देगा, और असल में सभी नेटवर्क ऑपरेशंस को तब तक समाप्त करना होगा जब तक नियंत्रक हो सकता है जारी किया गया (इसलिए dealloc में कनेक्शन रद्द करने में कोई बात नहीं है)।

मैंने प्रॉक्सी की निगरानी करने और दृश्य और पीछे के अंदर जल्दी से जाने के लिए यह कठिन तरीका सीखा। यह देखने के लिए वास्तव में आश्चर्यजनक था कि लंबित कनेक्शन ने अन्यथा अनजान एप्लिकेशन के लिए अतिरिक्त नेटवर्क बैंडविड्थ क्षति के 20 सेकंड तक पहुंचाया।

tl; डॉ नेटवर्क के लिए कतार का उपयोग करें, छवि प्रसंस्करण/स्केलिंग/जीयूआई अद्यतन के लिए जीसीडी।

+0

जीसीडी ब्लॉक केवल एक साथ चलेंगे यदि वे वैश्विक प्रेषण कतार पर भेजे जाते हैं। यदि आप एक धारावाहिक प्रेषण कतार (एक निजी प्रेषण कतार) बनाते हैं तो कार्य अनुक्रमिक रूप से चलाए जाते हैं। [ऐप्पल की कंसुरेंसी प्रोग्रामिंग गाइड] देखें (http://developer.apple.com/library/ios/#documentation/General/Conceptual/ConcurrencyProgrammingGuide/OperationQueues/OperationQueues.html)। –

+0

निश्चित रूप से, समस्या यह नहीं है कि आप नहीं जानते कि 'image_queue' क्या है, इसे' dispatch_get_global_queue (DISPATCH_QUEUE_PRIORITY_LOW, 0) 'असाइन किया जा सकता था। –

+0

@ ड्यूकन ऐसा लगता है कि एक धारावाहिक कतार का उपयोग करने में समस्या तब होती है जब चीजें पूरी तरह से अनुक्रमिक होती हैं, जो कि संकुचित समेकन होने के बजाय होती है जो maxConcurrentOperationCount Grzegorz के रूप में अनुमति देता है। – Lee

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