उद्देश्य-सी: एनएसएनोटिफिकेशन के लिए पर्यवेक्षक को कहां हटाया जाए?


102

मेरा एक ऑब्जेक्टिव सी क्लास है। इसमें, मैंने एक init मेथड बनाया और इसमें एक NSNotification स्थापित किया

//Set up NSNotification
[[NSNotificationCenter defaultCenter] addObserver:self 
                                         selector:@selector(getData)
                                             name:@"Answer Submitted"
                                           object:nil];

मैं [[NSNotificationCenter defaultCenter] removeObserver:self]इस कक्षा में कहाँ सेट करूँ ? मुझे पता है कि एक के लिए UIViewController, मैं इसे viewDidUnloadविधि में जोड़ सकता हूं तो अगर मुझे सिर्फ एक उद्देश्य सी क्लास बनाया जाए तो क्या करना होगा?


मैंने इसे डीलोकॉक विधि में रखा।
अनजाने

1
डीललोक पद्धति स्वचालित रूप से मेरे लिए नहीं बनाई गई थी जब मैंने उद्देश्य सी वर्ग बनाया था, इसलिए मेरे लिए इसे जोड़ना ठीक है?
जेन

हां, आप इसे लागू कर सकते हैं -(void)deallocऔर फिर इसमें जोड़ सकते हैं removeObserser:self। यह डाल करने के लिए सबसे अधिक अनुशंसित तरीका हैremoveObservers:self
पीटरसन

क्या अभी भी deallociOS 6 में इस विधि को रखना ठीक है ?
वॉचक्रैन

2
हां, एआरसी परियोजनाओं में डीललोक का उपयोग करना ठीक है, जब तक कि आप [सुपर डीलॉक] को नहीं बुलाते हैं (यदि आप [सुपर डीलॉक] कहते हैं तो आपको संकलक त्रुटि मिलेगी)। और हाँ, आप निश्‍चित रूप से अपने निष्कासन को डीलॉक में डाल सकते हैं।
फिल

जवाबों:


112

सामान्य उत्तर "जैसे ही आपको सूचनाओं की आवश्यकता नहीं होगी" होगा। यह स्पष्ट रूप से संतोषजनक जवाब नहीं है।

मेरा सुझाव है, कि आप उन कक्षाओं की [notificationCenter removeObserver: self]विधि में एक कॉल जोड़ते deallocहैं, जिसे आप पर्यवेक्षकों के रूप में उपयोग करने का इरादा रखते हैं, क्योंकि यह एक पर्यवेक्षक को सफाई से अपंजीकृत करने का अंतिम मौका है। हालाँकि, यह केवल सूचना केंद्रों द्वारा मृत वस्तुओं को सूचित करने के कारण होने वाली दुर्घटनाओं से आपकी रक्षा करेगा। यह आपके कोड को सूचनाएँ प्राप्त करने से नहीं बचा सकता है, जब आपकी वस्तुएँ अभी तक नहीं हैं / अब ऐसी स्थिति में नहीं हैं जिसमें वे ठीक से अधिसूचना को संभाल सकें। इसके लिए ... ऊपर देखें।

संपादित करें (चूंकि उत्तर मुझे लगता है कि अधिक टिप्पणियों को आकर्षित करने के लिए लगता है) सभी मैं यहां कहने की कोशिश कर रहा हूं: यह सामान्य रूप से सामान्य सलाह देने के लिए कठिन है जब अधिसूचना केंद्र से पर्यवेक्षक को निकालना सबसे अच्छा है, क्योंकि यह निर्भर करता है:

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

तो, सबसे अच्छी सामान्य सलाह मैं आपके साथ आ सकता हूं: अपने ऐप को सुरक्षित रखने के लिए। कम से कम एक संभावित विफलता के खिलाफ, removeObserver:नृत्य करें dealloc, क्योंकि यह अंतिम बिंदु (वस्तु के जीवन में) है, जहां आप उस सफाई से कर सकते हैं। इसका मतलब यह नहीं है: "जब तक deallocकहा जाता है तब तक निष्कासन को स्थगित करें , और सबकुछ ठीक हो जाएगा"। इसके बजाय, पर्यवेक्षक को हटा दें क्योंकि सूचनाएं प्राप्त करने के लिए ऑब्जेक्ट अब तैयार नहीं है (या आवश्यक है) । वह सटीक सही क्षण है। दुर्भाग्य से, ऊपर उल्लेख किए गए किसी भी प्रश्न के उत्तर को नहीं जानते हुए, मैं यह अनुमान भी नहीं लगा सकता कि वह क्षण कब होगा।

आप हमेशा removeObserver:एक वस्तु को कई बार सुरक्षित कर सकते हैं (और सभी लेकिन किसी दिए गए पर्यवेक्षक के साथ पहली बार कॉल करने से कुछ नहीं होगा)। इसलिए: इसे deallocकेवल सुनिश्चित करने के लिए (फिर से) करने के बारे में सोचें , लेकिन सबसे पहले और सबसे महत्वपूर्ण: इसे उचित समय पर करें (जो आपके उपयोग के मामले से निर्धारित होता है)।


4
यह एआरसी के साथ सुरक्षित नहीं है और संभावित रूप से रिसाव का कारण बन सकता है। इस डिस्कशन को देखें: cocoabuilder.com/archive/cocoa/311831-arc-and-dealloc.html
MobileMon

3
@MobileMon आप जिस लेख से जुड़े हैं, वह मेरी बात का संकेत देता है। मैं क्या खो रहा हूँ ?
डिर्क

मुझे लगता है कि यह ध्यान दिया जाना चाहिए कि एक को निरोधक के अलावा कहीं और प्रेक्षक को हटा देना चाहिए। उदाहरण के लिए, viewwilldisappear
MobileMon

1
@ मोबाइल मोबाइल - हाँ। मुझे उम्मीद है, कि मैं अपने जवाब के साथ मिल रहा हूँ। ऑब्ज़र्वर को हटाना deallocकेवल डिक्लोकेटेड ऑब्जेक्ट तक बाद में पहुंचने के कारण ऐप को क्रैश करने के खिलाफ बचाव की एक अंतिम पंक्ति है। लेकिन एक पर्यवेक्षक को अपंजीकृत करने का उचित स्थान आमतौर पर कहीं और है (और अक्सर, वस्तु के जीवन-चक्र में बहुत पहले)। मैं यहाँ कहने की कोशिश नहीं कर रहा हूँ "अरे, बस करो deallocऔर सब ठीक हो जाएगा"।
डिर्क

@MobileMon "उदाहरण के लिए, viewWillDisappear" एक ठोस सलाह देने के साथ समस्या यह है कि यह वास्तव में इस बात पर निर्भर करता है कि आप किस प्रकार की घटना के लिए पर्यवेक्षक के रूप में रजिस्टर करते हैं। यह s के लिए (या ) में एक पर्यवेक्षक को अपंजीकृत करने का सही समाधान हो सकता है , लेकिन यह वास्तव में उपयोग के मामले पर निर्भर करता है। viewWillDisappearviewDidUnloadUIViewController
डर्क

39

नोट: यह परीक्षण किया गया है और 100% प्रतिशत काम कर रहा है

तीव्र

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)

    if self.navigationController!.viewControllers.contains(self) == false  //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

PresentedViewController

override func viewWillDisappear(animated: Bool){
    super.viewWillDisappear(animated)

    if self.isBeingDismissed()  //presented view controller
    {
        // remove observer here
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
}

उद्देश्य सी

इसके रूप में iOS 6.0 > version, पर्यवेक्षक viewWillDisappearको viewDidUnloadविधि के रूप में हटाने के लिए बेहतर है।

 [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];

remove observerजब दृश्य को हटा दिया गया हो तो कई बार इसकी बेहतर स्थिति होती है navigation stack or hierarchy

- (void)viewWillDisappear:(BOOL)animated{
 if (![[self.navigationController viewControllers] containsObject: self]) //any other hierarchy compare if it contains self or not
    {
        // the view has been removed from the navigation stack or hierarchy, back is probably the cause
        // this will be slow with a large stack however.

        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}

PresentedViewController

- (void)viewWillDisappear:(BOOL)animated{
    if ([self isBeingDismissed] == YES) ///presented view controller
    {
        // remove observer here
        [[NSNotificationCenter defaultCenter] removeObserver:observerObjectHere];
    }
}

8
एक नियंत्रक को छोड़कर अभी भी सूचनाएं प्राप्त कर सकते हैं जब इसका दृश्य नहीं दिखाई दे रहा है (जैसे एक तालिका दृश्य पुनः लोड करने के लिए)।
वॉचक्रान

2
@wcochran अपने आप को पुनः लोड / रिफ्रेश करता हैviewWillAppear:
रिचर्ड

@Prince आप समझा सकते हैं कि क्यों देखेंWillDisapper बेहतर तो डीललोक? इसलिए हमने स्वयं में पर्यवेक्षक को शामिल किया है, इसलिए जब स्वयं को मेमोरी से हटा दिया जाएगा तो इसे डीललोक कहेंगे और फिर सभी पर्यवेक्षकों को हटा दिया जाएगा, क्या यह एक अच्छा तर्क नहीं है।
मटरू अलेक्जेंडर

जीवन चक्र की घटनाओं removeObserver:selfमें से किसी में कॉल UIViewControllerकरना आपके सप्ताह को बर्बाद करने की गारंटी है। अधिक पढ़ने: व्यक्तिपरक-
विशेषण- blogspot.com/2011/04/…

1
संकेत के रूप removeObserverमें कॉल को डालना viewWillDisappearनिश्चित रूप से जाने का सही तरीका है यदि नियंत्रक के माध्यम से प्रस्तुत किया जा रहा है pushViewController। यदि आप उन्हें deallocइसके स्थान पर रखते हैं तो deallocकभी नहीं बुलाया जाएगा - कम से कम मेरे अनुभव में ...
क्रिस्टोफर किंग

38

IOS 9 के बाद से अब पर्यवेक्षकों को हटाना आवश्यक नहीं है।

OS X 10.11 और iOS 9.0 NSNotificationCenter और NSDistributedNotificationCenter में अब पंजीकृत पर्यवेक्षकों को सूचनाएँ नहीं भेजी जाएंगी, जिन्हें डील किया जा सकता है।

https://developer.apple.com/library/mac/releasenotes/Foundation/RN-Foundation/index.html#10_11NotificationCenter


2
हो सकता है कि वे पर्यवेक्षकों को संदेश नहीं भेजेंगे, लेकिन मुझे विश्वास है कि वे मुझे समझने के लिए एक मजबूत संदर्भ रखेंगे। उस स्थिति में सभी पर्यवेक्षक स्मृति में रहेंगे और रिसाव उत्पन्न करेंगे। गलत हो तो मुझे सुधारो।
fir

6
लिंक किए गए दस्तावेज़ीकरण के बारे में विस्तार से बताया गया है। TL; DR: यह एक कमजोर संदर्भ है।
सेबस्टियन

लेकिन निश्चित रूप से यह तब भी आवश्यक है जब आप वस्तु को अपने आस-पास रख रहे हों और अभी सूचनाएँ नहीं सुनना चाहते हों
TheEye

25

यदि पर्यवेक्षक को एक दृश्य नियंत्रक में जोड़ा जाता है , तो मैं दृढ़ता से इसे जोड़ने viewWillAppearऔर इसे हटाने की सलाह देता हूं viewWillDisappear


मैं जिज्ञासु हूं, @RickiG: आप क्यों का उपयोग करने के लिए viewWillAppearऔर देखने के viewWillDisappearलिए सलाह देते हैं ?
इसहाक ओवरकेकर

2
@IsaacOveracker कुछ कारणों से: आपका सेटअप कोड (उदाहरण के लिए loadView और viewDidLoad) संभावित रूप से सूचनाओं को निकाल दिया जा सकता है और आपके नियंत्रक को यह दिखाने से पहले इसे प्रतिबिंबित करने की आवश्यकता है। यदि आप इसे इस तरह करते हैं तो कुछ लाभ हैं। उस समय जब आपने नियंत्रक को "छोड़ने" का फैसला किया, तो आप सूचनाओं के बारे में परवाह नहीं करते हैं और वे आपको तर्क करने के लिए प्रेरित नहीं करते हैं, जबकि नियंत्रक को स्क्रीन से दूर धकेला जा रहा है आदि ऐसे विशेष मामले हैं जहां नियंत्रक को सूचनाएं प्राप्त होनी चाहिए। ऑफ स्क्रीन मुझे लगता है कि आप ऐसा नहीं कर सकते। लेकिन इस तरह की घटनाएं शायद आपके मॉडल में होनी चाहिए।
रिकि डे

1
ARI के साथ @IsaacOveracker भी नोटिफिकेशन को अनसब्सक्राइब करने के लिए डीललॉक लागू करना अजीब होगा।
रिकाग

4
उन लोगों में से, जिन्होंने iOS7 के साथ UIViewControllers के साथ काम करने के दौरान पर्यवेक्षकों को पंजीकृत करने / निकालने का यह सबसे अच्छा तरीका है। एकमात्र पकड़ यह है कि, कई मामलों में आप नहीं चाहते कि पर्यवेक्षक को UINavigationController का उपयोग करते समय हटा दिया जाए और एक और UIViewController को स्टैक पर धकेल दिया जाए। समाधान: आप देख सकते हैं कि वीसी को देखने में पॉपअप किया जा रहा है। कॉल करके [self isBeDDississing] को कॉल कर सकते हैं।
लेकसिटी

नेविगेशन कंट्रोलर से व्यू कंट्रोलर को रोकने के कारण deallocतुरंत कॉल नहीं किया जा सकता है। व्यू कंट्रोलर में वापस जाने से कई सूचनाएं आ सकती हैं यदि प्रेक्षक को इनिशियलाइज़ेशन कमांड्स में जोड़ा जाता है।
जोनाथन लिन

20
-(void) dealloc {
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
}

4
मैं इन निर्देशों के क्रम को चारों ओर मोड़ देता हूँ ... के selfबाद का उपयोग [super dealloc]मुझे परेशान करता है ... (भले ही रिसीवर वास्तव में किसी भी तरह से सूचक को निष्क्रिय करने की संभावना नहीं है, ठीक है, आप कभी नहीं जानते, वे कैसे लागू हुए NSNotificationCenter)
डिर्क

हम्म। इसने मेरे लिए काम किया। क्या आपने कोई असामान्य व्यवहार देखा है?
लेगोलस

1
डिर्क सही है - यह गलत है। [super dealloc]हमेशा अपनी विधि का अंतिम विवरण होना चाहिए dealloc। यह आपकी वस्तु को नष्ट कर देता है; इसके चलने के बाद, आपके पास कोई मान्य selfनहीं है। / सीसी @Dirk
jscs

38
अगर iOS 5+ पर ARC का उपयोग किया जाता है, तो मुझे लगता [super dealloc]है कि अब इसकी आवश्यकता नहीं है
Pixelfreak

3
मजबूत @pixelfreak, यह कॉल [सुपर dealloc] के लिए एआरसी के तहत अनुमति नहीं है
tapmonkey


7

स्विचित उपयोग में डिनिट क्योंकि डीललोक अनुपलब्ध है:

deinit {
    ...
}

स्विफ्ट प्रलेखन:

क्लास इंस्टीट्यूशन डील होने से ठीक पहले एक डीइन्यूएस्टाइज़र को बुलाया जाता है। आप डीइनिटाइज़र को डिनिट कीवर्ड के साथ लिखते हैं, उसी तरह जैसे कि इंट्राइज़र को इनिट कीवर्ड के साथ लिखा जाता है। Deinitializers केवल वर्ग प्रकारों पर उपलब्ध हैं।

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


5

* संपादित करें: यह सलाह iOS <= 5 पर लागू होती है (यहां तक ​​कि आपको इसमें जोड़ना viewWillAppearऔर हटाना चाहिए viewWillDisappear- हालांकि यह सलाह लागू होती है यदि किसी कारण से आपने पर्यवेक्षक को जोड़ा है viewDidLoad)

आप जोड़ चुके हैं तो में पर्यवेक्षक viewDidLoadतुम दोनों में इसे निकाल देना चाहिए deallocऔर viewDidUnload। अन्यथा आप इसे दो बार जोड़ेंगे जब viewDidLoadबाद में बुलाया viewDidUnloadजाएगा (यह मेमोरी चेतावनी के बाद होगा)। यह आईओएस 6 में आवश्यक नहीं है जहां viewDidUnloadपदावनत किया जाता है और इसे नहीं बुलाया जाएगा (क्योंकि विचार अब स्वचालित रूप से अनलोड नहीं होते हैं)।


2
StackOverflow में आपका स्वागत है। कृपया मार्कडाउन एफएक्यू (प्रश्न / उत्तर संपादित करें बॉक्स के आगे प्रश्न चिह्न) देखें। मार्कडॉन का उपयोग करने से आपके उत्तर की उपयोगिता में सुधार होगा।
मार्क

5

मेरी राय में, निम्नलिखित कोड एआरसी में कोई मतलब नहीं है :

- (void)dealloc
{
      [[NSNotificationCenter defaultCenter] removeObserver:self];
      [super dealloc];
}

में IOS 6 , वहाँ भी में पर्यवेक्षकों को दूर करने में कोई मतलब नहीं है viewDidUnload, क्योंकि यह अब मान्य नहीं है।

योग करने के लिए, मैं हमेशा इसे करता हूं viewDidDisappear। हालाँकि, यह आपकी आवश्यकताओं पर भी निर्भर करता है, जैसे @Dirk ने कहा।


बहुत से लोग अभी भी iOS6 से पुराने संस्करणों के लिए कोड लिख रहे हैं। :-)
lnafziger

एआरसी में आप इस कोड का उपयोग कर सकते हैं लेकिन लाइन के बिना [सुपर डीलॉक]; आप यहाँ और अधिक देख सकते हैं: developer.apple.com/library/ios/#releasenotes/ObjectiveC/…
एलेक्स

1
क्या होगा यदि आपके पास एक नियमित NSObject एक अधिसूचना का पर्यवेक्षक हो? क्या आप इस मामले में डीललोक का उपयोग करेंगे?
क़िस्स

4

मुझे लगता है कि मुझे एक विश्वसनीय उत्तर मिला ! मेरे पास, जैसा कि ऊपर दिए गए उत्तर अस्पष्ट हैं और विरोधाभासी प्रतीत होते हैं। मैंने कुकबुक और प्रोग्रामिंग गाइड के माध्यम से देखा।

सबसे पहले, की शैली addObserver:में viewWillAppear:और removeObserver:में viewWillDisappear:मेरे लिए काम (मैं इसे परीक्षण किया) क्योंकि मैं जनक दृश्य नियंत्रक में कोड निष्पादित करने के लिए एक बच्चे को देखने के लिए नियंत्रक में एक अधिसूचना पोस्टिंग कर रहा हूँ नहीं है। मैं इस शैली का उपयोग केवल तभी करूंगा जब मैं एक ही दृश्य नियंत्रक के भीतर अधिसूचना के लिए पोस्ट कर रहा था और सुन रहा था।

उत्तर मैं सबसे ज्यादा भरोसा करूंगा, मुझे आईओएस प्रोग्रामिंग में मिला: बिग नर्ड रेंच गाइड 4। मुझे बीएनआर वालों पर भरोसा है क्योंकि उनके पास आईओएस प्रशिक्षण केंद्र हैं और वे सिर्फ एक और रसोई की किताब नहीं लिख रहे हैं। सटीक होना उनके हित में शायद है।

बीएनआर उदाहरण एक: addObserver:इन init:, removeObserver:इनdealloc:

बीएनआर उदाहरण दो: addObserver:इन awakeFromNib:, removeObserver:इनdealloc:

... जब dealloc:वे प्रेक्षक को हटाने में उपयोग नहीं करते हैं[super dealloc];

मुझे आशा है कि यह अगले व्यक्ति की मदद करता है ...

मैं इस पोस्ट को अपडेट कर रहा हूं क्योंकि Apple अब स्टोरीबोर्ड के साथ लगभग पूरी तरह से चला गया है इसलिए उपरोक्त सभी स्थितियों पर लागू नहीं हो सकता है। महत्वपूर्ण बात (और कारण मैंने इस पोस्ट को पहली जगह में जोड़ा है) यदि आपका viewWillDisappear:कॉल हो रहा है तो ध्यान देना है। यह मेरे लिए नहीं था जब आवेदन पृष्ठभूमि में प्रवेश किया।


यह कहना मुश्किल है कि क्या यह सही है क्योंकि संदर्भ महत्वपूर्ण है। यह कुछ समय पहले ही उल्लेख किया गया है, लेकिन डीलॉक एक एआरसी संदर्भ (जो अब तक केवल संदर्भ है) में बहुत कम समझ में आता है। यह भी अनुमान लगाने योग्य नहीं है जब डीललोक कहा जाता है - viewWillDisappear को नियंत्रित करना आसान है। एक पक्ष ध्यान दें: यदि आपके बच्चे को कुछ संवाद करने की आवश्यकता है, तो यह एक बेहतर विकल्प की तरह है।
रिकागि

2

स्वीकृत उत्तर सुरक्षित नहीं है और स्मृति रिसाव का कारण बन सकता है। कृपया डीलरॉक में अपंजीकृत को छोड़ दें, लेकिन यह भी देखें कि डीडिस्टरडियर में है (यदि आप दृश्य में पंजीकरण करते हैं तो निश्चित रूप से है) .... यह मैं किसी भी तरह से नहीं जानता हूं और यह बहुत अच्छा है! :)


1
मैं इस जवाब से सहमत हूं। मैं स्मृति चेतावनी का अनुभव करता हूं और ऐप के गहन उपयोग के बाद क्रैश होने की सूचना देता हूं, अगर मैं देखने वालों को हटा नहीं पाऊं तो चिल्लाना।
सर्पड्रेग

2

यह भी ध्यान रखना महत्वपूर्ण है कि viewWillDisappearयह भी कहा जाता है जब दृश्य नियंत्रक एक नया यूआईवाईयूवाई पेश करता है। यह प्रतिनिधि केवल यह दर्शाता है कि दृश्य नियंत्रक मुख्य दृश्य डिस्प्ले पर दिखाई नहीं दे रहा है।

इस स्थिति में, viewWillDisappearयदि हम UIview को मूल माता-पिता नियंत्रक के साथ संवाद करने की अनुमति देने के लिए अधिसूचना का उपयोग कर रहे हैं, तो अधिसूचना को निपटाना असुविधाजनक हो सकता है।

एक समाधान के रूप में मैं आमतौर पर पर्यवेक्षक को इन दो तरीकों में से एक में हटा देता हूं:

- (void)viewWillDisappear:(BOOL)animated {
    NSLog(@"viewController will disappear");
    if ([self isBeingDismissed]) {
        NSLog(@"viewController is being dismissed");
        [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
    }
}

-(void)dealloc {
    NSLog(@"viewController is being deallocated");
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"actionCompleted" object:nil];
}

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

- (void)viewWillAppear:(BOOL)animated {
    NSLog(@"viewController will appear");
    // Add observers
    [[NSNotificationCenter defaultCenter] removeObserver:self name:@"imageGenerated" object:nil]; // This is added to avoid duplicate notifications when the view is presented again
    [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(receivedImageFromCameraOrPhotolibraryMethodOnListener:) name:@"actionCompleted" object:nil];

}

-1

स्विफ्ट 3

सूचनाओं का उपयोग करने के दो मामले हैं: - वे केवल तभी आवश्यक हैं जब दृश्य नियंत्रक स्क्रीन पर हो; - उन्हें हमेशा जरूरत होती है, भले ही उपयोगकर्ता ने वर्तमान में एक और स्क्रीन खोली हो।

पहले मामले के लिए पर्यवेक्षक को जोड़ने और हटाने के लिए सही जगह हैं:

/// Add observers
///
/// - Parameter animated: the animation flag
override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(...)
}

/// Remove observers
///
/// - Parameter animated: the animation flag
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self)
}

दूसरे मामले के लिए सही तरीका है:

/// Add observers
override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(...)
}

/// Remove observers
///
/// - Parameter animated: the animation flag
override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    if self.isBeingDismissed // remove only when view controller is removed disappear forever
    || !(self.navigationController?.viewControllers.contains(self) ?? true) {
        NotificationCenter.default.removeObserver(self)
    }
}

और डाल कभी नहीं removeObserverमें deinit{ ... }है - यह एक गलती है!


-1
override func viewDidLoad() {   //add observer
  super.viewDidLoad()
  NotificationCenter.default.addObserver(self, selector:#selector(Yourclassname.method), name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}

override func viewWillDisappear(_ animated: Bool) {    //remove observer
    super.viewWillDisappear(true)
    NotificationCenter.default.removeObserver(self, name: NSNotification.Name(rawValue: "NotificationIdentifier"), object: nil)
}
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.