2009-01-01 13 views
8

मेरे पास ऐसा कोई मामला है जहां बच्चा दृश्य अपने मूल दृश्य में अधिसूचना भेजता है। अब मैं viewWillAppear: और removeObserver:viewWillDisappear: में कॉल कर रहा हूं। लेकिन, मुझे लगता है कि रीफ्रेश होने पर viewWillAppear: कॉल के बाद यह सही नहीं है।addObserver को कॉल करने और निकालने के लिए संभावित स्थान

[[NSNotificationCenter defaultCenter] addObserver: (id)observer selector: (SEL)aSelector name: (NSString *)aName object: (id)anObject]; 

[[NSNotificationCenter defaultCenter] removeObserver: (id)observer name: (NSString *)aName object: (id)anObject]; 

धन्यवाद।

उत्तर

5

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

एक बेहतर समाधान या तो एक झंडा सेट करने के लिए है जिसे आपने पंजीकृत किया है, या अपनी init विधि में पंजीकरण करने के लिए है।

+0

क्या यह सच है कि 'dealloc' हमेशा नहीं कहा जाता है?'Init' में 'addObserver' को कॉल करना सुरक्षित होगा और' viewDidUnload' में' removeObserver' को कॉल करें - या यह योजना मेरे व्यू कंट्रोलर को मेमोरी चेतावनी के बाद एक बार फिर लोड होने के बाद पुन: पंजीकृत नहीं करेगी (जिसके कारण दृश्य अनलोड होने के बाद से यह दिखाया नहीं गया था)? – matm

+3

इस मामले में RemoveObserver कहां रखना है, इस पर अभी भी स्पष्ट नहीं है। – Resh32

+1

याद रखें कि 'viewDidUnload' को आईओएस 6.0 के बाद बहिष्कृत किया गया है ... – DanSkeel

1

मुझे लगता है कि अधिसूचना के लिए पंजीकरण करने के लिए सही स्थिति viewDidLoad विधि है, और उसी अधिसूचनाओं के लिए पंजीकरण रद्द करने की सही स्थिति dealloc विधि है।

+0

लेकिन जब स्मृति चेतावनी प्राप्त होती है, तो viewDidUnload को कॉल किया जाएगा, लेकिन डीलोक नहीं, जब इस व्यू कंट्रोलर पर वापस जाएं, तो देखेंडिडलोड फिर से कॉल किया जाएगा, फिर, आपका नोटिस फिर से पंजीकृत होगा। – ZYiOS

+1

आप सही हैं। यह पोस्ट बहुत पुरानी है, इसलिए इसे अनदेखा करें। महत्वपूर्ण बात यह है कि रजिस्टर को संतुलित करना और कॉल रद्द करना महत्वपूर्ण है। या तो अपनी सूचनाओं को पंजीकृत और अनधिकृत करने के लिए viewDidLoad और viewDidUnload, या viewDidLoad (ध्वज के साथ) और dealloc, या init और dealloc देखें। प्रासंगिक जानकारी के लिए बेन गॉटलिब की टिप्पणी देखें। – Mustafa

+0

पता नहीं है कि यह सही है या नहीं, लेकिन मैं इसे अपना रास्ता देता हूं। और याद रखें कि ID 6.0 के बाद viewDidUnload को बहिष्कृत किया गया है ... – DanSkeel

0

बेन का अधिकार - लेकिन मुझे इसके चारों ओर एक और संभावित रूप से नाजुक, रास्ता मिला। मैंने अभी यह खोज लिया क्योंकि मुझे हमेशा "... को हटा दिया गया था जबकि मुख्य मूल्य पर्यवेक्षक अभी भी इसके साथ पंजीकृत थे"

मुझे नहीं पता कि क्यों - लेकिन जब मैंने अपने init विधि में addObserver जोड़ा था, और ऑब्सर्वर को हटा दिया मेरी डीलोक विधि - मुझे अभी भी केवीओ मिल रहा था संदेश अभी भी देखा जा रहा था। मैंने कदम बढ़ाया और सत्यापित किया कि मेरा निकालना ऑब्सर्वर सही ढंग से बुलाया जा रहा था।

मैंने अपने addobserver को देखने के बजायडिडलोड विधि में स्थानांतरित कर दिया, और यह काम करने लग रहा था।

मैंने देखने में एक निकास ऑब्सर्वर छोड़ दिया DidUnload और dealloc में; लेकिन मुझे यह पसंद नहीं है क्योंकि यह संतुलित नहीं है। लेकिन सामान्य परिस्थितियों में, मेरा viewDidUnload को कॉल नहीं किया जाता है - अगर मुझे कम स्मृति अधिसूचना मिलती है तो यह केवल सुरक्षा है।

लेकिन मैं संभावित रूप से उस स्थिति में पहुंच सकता हूं जहां कम स्मृति घटना आती है, viewDidUnload को कॉल किया जाता है। अगर मैं उसके बाद कुछ समय बाद डेलोक दबाता हूं (इससे पहले कि मैं फिर से दृश्यलोड को हिट करता हूं), मैं हटाने के लिए दो बार कॉल कर दूंगा!

तो, मुझे लगता है कि मैं इसे अपने दृश्य में रखूंगा, और मेरे डीलोक।

मुझे अभी भी पता नहीं है कि अगर मैं अपने init विधि में addobserver करता हूं तो यह सही क्यों नहीं काम करता है।

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