2011-11-07 11 views
13

यह किसी iOS एप्लिकेशन के मुख्य थ्रेड के लिए वापस संचार के लिए सूचना का उपयोग करने के लिए ठीक है? (सीएफ प्रदर्शन चयनकर्ताऑनमेन थ्रेड)। यही है, इस उद्देश्य के लिए कोई गोटो है?क्या आईओएस ऐप के मुख्य थ्रेड पर संचार के लिए अधिसूचना का उपयोग करना ठीक है? (सीएफ performSelectorOnMainThread)

पृष्ठभूमि

  • वापस एक पृष्ठभूमि धागा (जैसे performSelectorInBackground)
  • performSelectorOnMainThread इस्तेमाल कर सकते हैं वापस संवाद करने के लिए से मुख्य यूआई धागा करने के लिए कॉल करने के लिए चाहते हैं, लेकिन सोच अगर यह किसी सूचना का उपयोग करने के लिए ठीक है?

उदाहरण

[[NSNotificationCenter defaultCenter] postNotificationName:@"ModelChanged" object:self]; 

उत्तर

20

असल में वहाँ एक gottcha है; आप यादृच्छिक रूप से क्रैश करेंगे! यह मेरा अनुभव रहा है। इसे इस तथ्य के साथ करना है कि अधिसूचना प्राप्त करने वाली वस्तु अधिसूचना के प्रेषक के समान धागे पर होती है।

Apple iOS Documentation on Notification Centers से:

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

यह अनिवार्य रूप से आपको सिरदर्द का कारण बन जाएगा।

अधिसूचना मुख्य थ्रेड पर कुछ द्वारा प्राप्त किया जा रहा है, तो मैंने पाया कि पृष्ठभूमि धागे से मुख्य थ्रेड में पॉपिंग एक अधिसूचना जारी करने के लिए इस बारे में जाने के लिए सबसे सुरक्षित तरीका है। यह काफी ऐसा करने के लिए सरल है:

//Call this to post a notification and are on a background thread  
- (void) postmyNotification{ 
    [self performSelectorOnMainThread:@selector(helperMethod:) withObject:Nil waitUntilDone:NO]; 
} 

//Do not call this directly if you are running on a background thread. 
- (void) helperMethod{ 
    [[NSNotificationCenter defaultCenter] postNotificationName:@"SOMENAME" object:self]; 
} 

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

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

आशा है कि मदद मिली।

+1

मैंने इस समस्या को मेरे उत्तर में एक टिप्पणी में संदर्भित किया। मुझे अधिसूचना और पर्यवेक्षक पोस्ट करने वाले ऑब्जेक्ट के बीच युग्मन के आपके समाधान को ठीक तरह से बी/सी पसंद नहीं है। ऑब्जेक्ट पोस्टिंग को जो भी थ्रेड पसंद है उसे पोस्ट करना चाहिए। रिसीवर को उस थ्रेड पर अधिसूचना को संभालना चाहिए जिसकी आवश्यकता है (उदा। रिसीवर मुख्य थ्रेड या किसी अन्य थ्रेड पर अधिसूचना अग्रेषित कर सकता है)। ऐप्पल इस विधि का नमूना कोड में भी उपयोग करता है। – XJones

+0

मैं पूरी तरह से सहमत हूं। मैंने इस विधि को दर्शाने के लिए अपना जवाब अपडेट कर लिया है। – PixelCloudSt

+0

@ पिक्सेल क्लाउडस्ट मैं इस विधि में युग्मन को समझता हूं, लेकिन रिसीवर को कई धागे पर सुनने के बारे में कैसे जाना होगा? –

8

हाँ के लिए, सूचनाएं इस उद्देश्य के लिए इस्तेमाल किया जा सकता। आप थ्रेड में ऑब्जेक्ट्स के बीच संवाद करने के लिए अपनी पसंद की किसी भी विधि (प्रोटोकॉल, सूचनाएं, प्रत्यक्ष संदेश) का उपयोग कर सकते हैं। आप जो भी चुनते हैं उस पर निर्भर करता है जो आपको लगता है वह सबसे उपयुक्त है। सूचनाएं महान होती हैं जब अधिसूचना पोस्ट करने वाली वस्तु अधिसूचना को देखते हुए वस्तुओं के बारे में कुछ नहीं जानती है। आपके द्वारा संदेश भेजने दें (उदाहरण के performSelectorOnMainThread) तो वस्तु संदेश भेजने वस्तु (आमतौर पर एक प्रोटोकॉल के माध्यम से) यह करने के लिए संदेश दे रहा है के बारे में पता करने की जरूरत है।

+0

ठीक है धन्यवाद - मुझे कुछ समस्याएं हैं (http://stackoverflow.com/questions/8032987/why-do-i-get-wait-fences-failed-to-receive-reply-for-this-code) और सोच रहा है कि यह – Greg

+1

ठीक कारण हो सकता है, बस उस पर एक उत्तर पोस्ट किया। मैं आम तौर पर प्रेषक पर हैंडलर में किसी भी थ्रेड आवश्यकताओं को लागू करने के लिए बेहतर लगता हूं। उदाहरण के लिए, आप यह सुनिश्चित कर सकते हैं कि आप हमेशा मुख्य धागे पर अधिसूचनाएं पोस्ट करते हैं लेकिन यह कठिन है। पोस्टिंग ऑब्जेक्ट परवाह नहीं करना चाहिए।प्राप्तकर्ता देखभाल करता है और उचित होने पर संदेश को मुख्य धागे पर अग्रेषित करना चाहिए। – XJones

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