14

संभव डुप्लिकेट:
Grand Central Dispatch (GCD) vs. performSelector - need a better explanationdispatch_async का उपयोग करके मुख्य थ्रेड पर यूआई परिवर्तन करें या प्रदर्शन चयन करेंऑनमेन थ्रेड?

मुख्य थ्रेड पर "सामान" पर अमल करने के लिए, मैं dispatch_async या performSelectorOnMainThread इस्तेमाल करना चाहिए? क्या कोई पसंदीदा तरीका है, सही/या गलत, और/या सर्वोत्तम अभ्यास?

उदाहरण: मैं NSURLConnection sendAsynchronousRequest:urlRequest विधि के ब्लॉक के भीतर कुछ तर्क कर रहा हूं। क्योंकि मैं मुख्य दृश्य में सामान कर रहा हूं जैसे UIAlertView प्रस्तुत करने के लिए मुझे मुख्य धागे पर UIAlertView दिखाना होगा। ऐसा करने के लिए मैं निम्नलिखित कोड का उपयोग कर रहा हूँ।

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

    // code snipped out to keep this question short 

    if(![NSThread isMainThread]) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
        [alertView show]; 
     }); 
    } 
}]; 

उसी if(![NSThread isMainThread]) कथन के भीतर मैं कुछ कस्टम तरीकों को भी कॉल करता हूं। सवाल यह है कि, क्या मुझे ऊपर उपयोग कर रहे dispatch_async विधि का उपयोग करना चाहिए या इसके बजाय performSelectorOnMainThread का उपयोग करना बेहतर है? उदाहरण के लिए, नीचे पूर्ण कोड:

[NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) { 

    // code snipped out to keep this question short 

    if(![NSThread isMainThread]) 
    { 
     dispatch_async(dispatch_get_main_queue(), ^{ 
        UIAlertView *alertView = [[UIAlertView alloc] initWithTitle:@"Oops!" message:@"Some Message" delegate:self cancelButtonTitle:@"OK" otherButtonTitles:nil]; 
        [alertView show]; 

      // call custom methods in dispatch_async? 
      [self hideLoginSpinner]; 
     }); 

     // or call them here using performSelectorOnMainThread??? 
     [self performSelectorOnMainThread:@selector(hideLoginSpinner) withObject:nil waitUntilDone:NO]; 
    } 
}]; 

FYI करें - अगर मैं करते वह मुख्य थ्रेड पर इन कार्यवाहियों को नहीं मैं कुछ सेकंड की देरी जब UIAlertView पेश देख सकते हैं और मैं डिबगर wait_fences: failed to receive reply: 10004003 में निम्न संदेश प्राप्त होता है। मैंने सीखा है कि ऐसा इसलिए है क्योंकि आपको मुख्य धागे पर UI में परिवर्तन करने की आवश्यकता है ... यदि कोई सोच रहा है कि मैं ऐसा क्यों कर रहा हूं जो मैं कर रहा हूं ...

+2

निकट से संबंधित: [क्या performSelectorOnMainThread बीच क्या अंतर है? मुख्य कतार पर और dispatch_async()] (http://stackoverflow.com/questions/9335434/) –

+2

_writing_ कोड की पीओवी से सबसे स्पष्ट अंतर यह है कि एक ब्लॉक प्रेषण अधिक लचीला है: उदाहरण के लिए, आदिम तर्कों को संभालना आसान तरीका है। –

उत्तर

14

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

  1. dispatch_async का बड़ा फायदा यह है कि संकलक अपने सभी सामान्य परीक्षण करता है। यदि आप performSelectorOnMainThread में विधि को गलत टाइप करते हैं तो आप समय संकलित करने के बजाए रन टाइम पर असफल हो जाते हैं।
  2. dispatch_async__block क्वालीफायर का उपयोग करके मुख्य धागे से डेटा वापस करना अधिक आसान बनाता है।
  3. dispatch_async आदिम तर्कों को संभालने में बहुत आसान बनाता है क्योंकि आपको उन्हें किसी ऑब्जेक्ट में लपेटना नहीं है। हालांकि, यह एक संभावित pitfall के साथ आता है। यदि आपके पास कुछ डेटा के लिए पॉइंटर है तो याद रखें कि ब्लॉक कैप्चर डेटा की गहरी प्रतिलिपि नहीं करता है। दूसरी ओर किसी ऑब्जेक्ट में डेटा को लपेटने के रूप में आपको performSelectorOnMainThread के लिए करने के लिए मजबूर होना होगा गहरी प्रतिलिपि (जब तक आप विशेष विकल्प सेट नहीं करते)। एक गहरी प्रतिलिपि के बिना आप अंतःक्रियात्मक बग में भाग सकते हैं जो डीबग करने के लिए निराशाजनक हैं। तो इसका मतलब है कि dispatch_async पर कॉल करने से पहले NSString में char * जैसी चीज़ें लपेटनी चाहिए।
+0

1. 'performSelectorOnMainThread' अब एक अविकसित-चयनकर्ता चेतावनी दिखाता है। – ma11hew28

+0

यदि आप एक्सकोड बिल्ड सेटिंग्स में अंडरक्लेयर सिलेक्टर चेतावनी चालू करते हैं तो आपको किसी भी समय @some_ बिल्ड टाइम परीक्षण मिल जाता है @selector का उपयोग किया जाता है, जिसमें 'performSelectorOnMainThread'' शामिल है।यह टाइपो के साथ मदद करता है, लेकिन इस चेतावनी की सीमाओं से अवगत रहें। यह जांचता है कि क्या किसी मिलान करने वाले चयनकर्ता को अभी तक घोषित नहीं किया गया है, न केवल उन ऑब्जेक्ट्स के लिए जिन्हें आप 'प्रदर्शन चयनकर्ता ऑनमैन थ्रेड' पर कॉल कर रहे हैं। दूसरा, यह कोडिंग शैली सम्मेलन को लागू करता है कि उपयोग किए जाने से पहले विधियों और चयनकर्ताओं को घोषित किया जाना चाहिए। –

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