2012-02-17 16 views
52

मुझे थ्रेड के अंदर एक दृश्य को संशोधित करने में समस्याएं आ रही थीं। मैंने एक सबव्यूव जोड़ने की कोशिश की लेकिन इसे प्रदर्शित करने में लगभग 6 या अधिक सेकंड लग गए। आखिर में यह काम कर रहा है, लेकिन मुझे नहीं पता कि वास्तव में कैसे। तो मैं सोच रहा था क्यों यह काम किया है और क्या निम्न विधियों के बीच का अंतर है:मुख्य कतार पर performSelectorOnMainThread और dispatch_async के बीच क्या अंतर है?

//this worked -added the view instantly 
dispatch_async(dispatch_get_main_queue(), ^{ 
    //some UI methods ej 
    [view addSubview: otherView]; 
} 

//this took around 6 or more seconds to display 
[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView 
waitUntilDone:NO]; 

//Also didnt work: NSNotification methods - took also around 6 seconds to display 
//the observer was in the viewController I wanted to modify 
//paired to a method to add a subview. 
[[NSNotificationCenter defaultCenter] postNotificationName: 
@"notification-identifier" object:object]; 

संदर्भ के लिए इस ACAccountStore के वर्ग के इस Completetion हैंडलर के अंदर बुलाया गया।

accountStore requestAccessToAccountsWithType:accountType withCompletionHandler:^(BOOL granted, NSError *error) { 
      if(granted) { 
      //my methods were here 
      } 
} 

संपादित करें: जब मैं कहता हूं कि यह काम नहीं करता है तो मेरा मतलब है कि मैंने जो दृश्य जोड़ा है उसे प्रदर्शित करने में लगभग 6 सेकंड लग गए।

+0

जब आप कहते हैं कि 'प्रदर्शन चयनकर्ता ओनमेन थ्रेड:' काम नहीं किया, यह कैसे विफल हुआ? क्या आपको एक त्रुटि संदेश मिला? क्या यह एक रनटाइम त्रुटि संकलन त्रुटि था? अगर आपको कोई त्रुटि नहीं मिली है, तो आप कैसे जानते हैं कि यह असफल रहा? –

+0

क्या 'addSubview:' आपके द्वारा उपयोग की जाने वाली एकमात्र विधि यूआई तत्वों को छुआ है, या अन्य भी हैं? –

+0

@AndrewMadsen मैं यह उल्लेख करना भूल गया कि यह काम करता है लेकिन इसे प्रदर्शित करने में लगभग 6 या अधिक सेकंड लग गए। –

उत्तर

69

डिफ़ॉल्ट रूप से, -performSelectorOnMainThread:withObject:waitUntilDone: केवल डिफ़ॉल्ट रन लूप मोड में चलाने के लिए चयनकर्ता को शेड्यूल करता है। यदि रन लूप किसी अन्य मोड (जैसे ट्रैकिंग मोड) में है, तो यह तब तक नहीं चलेगा जब तक कि रन लूप डिफ़ॉल्ट मोड पर वापस स्विच न हो जाए। आप इसे -performSelectorOnMainThread:withObject:waitUntilDone:modes: संस्करण के साथ प्राप्त कर सकते हैं (उन सभी मोड को पार करके जिन्हें आप इसे चलाने के लिए चाहते हैं)।

दूसरी तरफ, dispatch_async(dispatch_get_main_queue(), ^{ ... }) जैसे ही मुख्य रन लूप नियंत्रण ईवेंट को वापस लौटता है, ब्लॉक को वापस चलाएगा। यह मोड के बारे में परवाह नहीं है। इसलिए यदि आप मोड के बारे में परवाह नहीं करना चाहते हैं, तो dispatch_async() जाने का बेहतर तरीका हो सकता है।

+1

मोड क्या हैं, और मुझे उनकी परवाह कब करनी चाहिए? – ma11hew28

+2

@MattDiPasquale: आईओएस पर, आप मूल रूप से उन्हें अनदेखा कर सकते हैं, रनलोप आमतौर पर हमेशा डिफ़ॉल्ट मोड में चलता है। ओएस एक्स पर 3 और मोड हैं जिन्हें आप देख सकते हैं, 'एनएससीओनेक्शन रीप्लीमोड',' एनएसएमओडल पैनेललुन लूपमोड ', और' एनएसईएन्टेंटट्रैकिंग लुनलूपोड '। यदि आप रुचि रखते हैं तो आप उन लोगों के लिए दस्तावेज़ देख सकते हैं। –

+2

ध्यान दें कि आईओएस UITrackingRunLoopMode में कुछ टच इवेंट ट्रैकिंग के लिए उपयोग किया जाता है (जब एक UIScrollView एक स्पर्श आंदोलन को ट्रैक कर रहा है)। – cdemiris99

0

आप के साथ waitUntilDone=YES

जैसे PerformSelectorOnMainThread कोशिश किया:

कोड:

[viewController performSelectorOnMainThread:@selector(methodThatAddsSubview:) withObject:otherView waitUntilDone:YES]; 

मुझे लगता है कि क्यों PerformSelectorOnMainThread तो प्रतिक्रिया करने के लिए समय लगता है के रूप में इस मुद्दे को हल कर सकते हैं।

1

ऐसा लगता है क्योंकि performSelectorOnMainThread:withObject:waitUntilDone: सामान्य रन लूप मोड के साथ संदेश पंक्तिबद्ध करता है। Apple's Concurrency Programming Guide के अनुसार, मुख्य कतार ऐप के रन लूप से अन्य घटनाओं के साथ कतारबद्ध कार्यों को अंतःस्थापित करेगी। इस प्रकार, यदि घटना कतार में अन्य घटनाओं को संसाधित किया जाना है, तो प्रेषण कतार में पंक्तिबद्ध ब्लॉक पहले चलाए जा सकते हैं, भले ही उन्हें बाद में सबमिट किया गया हो।

This articleperformSelectorOnMainThread बनाम dispatch_async के लिए एक शानदार स्पष्टीकरण है, जो उपरोक्त प्रश्न का उत्तर भी देता है।