स्विफ्ट में NSNotification के लिए प्रेक्षक को कहां से हटाएं?


83

मैं NSNotificationस्विफ्ट के लिए पर्यवेक्षक को कहां से हटाऊं, कब से उपलब्ध हैं viewDidUnloadऔर dealloc()अनुपलब्ध हैं?


जब तक आप ब्लॉक-शैली का उपयोग नहीं कर रहे हैं, आजकल आपको उन्हें मैन्युअल रूप से हटाने की आवश्यकता नहीं है।
फेटी

जवाबों:


71

नीचे दिए गए विधि का उपयोग करें जो समान रूप से कार्य करता है dealloc

deinit {
    // Release all resources
    // perform the deinitialization
}

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

स्विफ्ट Deinitializer


13
नीचे दिए गए एक उत्तर के अनुसार, iOS 9 के रूप में, पर्यवेक्षकों को स्वचालित रूप से आपके लिए हटा दिया जाता है जब तक कि आप ब्लॉक-आधारित का उपयोग नहीं कर रहे हैं।
Crashalot

deinitजब ViewControllerB धक्का होगा, तो ViewControllerA के लिए @ कामाई विधि नहीं कहा जाएगा।
अनिरुद्ध महाले

@AnirudhaMahale - नहीं, क्योंकि ViewControllerA अभी भी नेविगेशन कंट्रोलर के स्टैक में है। deinitViewControllerA के लिए केवल तभी कहा जाएगा जब यह नेविगेशन कंट्रोलर के स्टैक में न हो। उदाहरण के लिए: rootViewController पर स्विच करना (यदि rootViewController ViewControllerA नहीं है)
Kampai

@Kampai: यह काम नहीं करेगा जैसे कि आप दृश्य नियंत्रक में पर्यवेक्षक जोड़ रहे हैं। उच्च संभावना है कि इसे रिटेन चक्र के तहत पकड़ा जाएगा और बिल्कुल भी कॉल नहीं करेगा deinit। कॉल करने के लिए आदर्श स्थानfunc viewDidDisappear(_ animated: Bool)
भानु बिरानी

@ भानुबिरानी: क्या आप कृपया किसी भी मामले की व्याख्या कर सकते हैं, आप "उच्च संभावना" के बारे में बता रहे हैं। खैर मेरे अनुभव में मुझे कोई सामना नहीं करना पड़ा।
कंपाई

136

के रूप में आईओएस 9 (और ओएस एक्स 10.11), आप पर्यवेक्षकों को दूर करने की जरूरत नहीं है अगर आप ब्लॉक आधारित पर्यवेक्षकों हालांकि उपयोग नहीं कर रहे अपने आप को,। सिस्टम इसे आपके लिए करेगा, क्योंकि यह पर्यवेक्षकों के लिए शून्यिंग-कमजोर संदर्भों का उपयोग करता है, जहां यह हो सकता है।

और यदि आप ब्लॉक आधारित पर्यवेक्षकों का उपयोग कर रहे हैं, तो सुनिश्चित करें कि आप क्लोजर की कैप्चर सूची का उपयोग करके स्वयं को कमजोर रूप से कैप्चर करते हैं [weak self], और पर्यवेक्षक को deinitविधि में हटा दें । यदि आप स्वयं के लिए कमजोर संदर्भ का उपयोग नहीं करते हैं, तो deinitविधि (और इस प्रकार उस पर्यवेक्षक को हटाने) को कभी भी कॉल नहीं किया जाएगा क्योंकि अधिसूचना केंद्र अनिश्चित काल तक इसका एक मजबूत संदर्भ रखेगा।

अधिक जानकारी OS X v10.11 और iOS 9 के लिए फाउंडेशन रिलीज नोट्स पर मिल सकती है ।

यदि पर्यवेक्षक को शून्य-कमजोर संदर्भ के रूप में संग्रहीत किया जा सकता है, तो अंतर्निहित भंडारण पर्यवेक्षक को एक शून्य कमजोर संदर्भ के रूप में संग्रहीत करेगा, यदि वैकल्पिक रूप से ऑब्जेक्ट को कमजोर रूप से संग्रहीत नहीं किया जा सकता है (अर्थात इसमें कस्टम अनुरक्षण / रिलीज तंत्र है जो रनटाइम को रोक देगा; ऑब्जेक्ट को कमजोर रूप से संग्रहीत करने में सक्षम होने से) यह ऑब्जेक्ट को गैर-कमजोर शून्यिंग संदर्भ के रूप में संग्रहीत करेगा। इसका मतलब यह है कि पर्यवेक्षकों को अपने निपटान पद्धति में संयुक्त राष्ट्र के पंजीकरण की आवश्यकता नहीं है।

- [NSNotificationCenter addObserverForName: ऑब्जेक्ट: कतार: usingBlock] विधि के माध्यम से ब्लॉक स्थित पर्यवेक्षकों को अभी भी संयुक्त राष्ट्र के पंजीकृत होने की आवश्यकता है जब सिस्टम अब भी इन पर्यवेक्षकों के लिए एक मजबूत संदर्भ नहीं रखता है।


1
मैं उत्सुक हूं, क्या यह प्रतिनिधियों के लिए समान काम करता है? मैंने iOS8 में देखा है, डेलिगेट्स मेमोरी पर कब्जा करते हैं और रिटेन नहीं करते हैं। मैं विधि delegate = nilमें लिखता था dealloc()। क्या यह अब से वही काम करता है?
कंपाई

1
एक सामान्य नियम के रूप में प्रतिनिधियों को कमजोर संदर्भ के रूप में घोषित किया जाना चाहिए और किसी अन्य कार्य की आवश्यकता नहीं है।
निकोला मिलिसविक

चूंकि आपने विशेष रूप से उल्लेख किया है कि यह ब्लॉक आधारित पर्यवेक्षकों के लिए काम नहीं करता है: क्या आप विस्तार से बता सकते हैं कि क्यों? क्या उसके आसपास कोई रास्ता है? उदा। [कमजोर स्व]
फिलिप जेहोडा

62

आप तीन तरीकों का उपयोग कर सकते हैं:

  1. के बाद popViewController, वापस navigationControllerया dismissViewControllerAnimated:

    deinit {
        print("Remove NotificationCenter Deinit")
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  2. viewDidDisappear, इसे हटाने के बाद यह पहले से ही अगले नियंत्रक है:

    override func viewDidDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    
  3. viewWillDisappear - अगला दृश्य खोलने से पहले:

    override func viewWillDisappear(animated: Bool) {
        NSNotificationCenter.defaultCenter().removeObserver(self)
    }
    

स्विफ्ट 3.0 सिंटैक्स:

NotificationCenter.default.removeObserver(self)

1
मुझे लगता है कि सबसे अच्छा विकल्प है।
ग्लेन पोसादास

IOS 9 के रूप में, @ नोइकोला मिलिसविक के अनुसार, पर्यवेक्षकों को स्वचालित रूप से आपके लिए हटा दिया जाता है जब तक कि आप ब्लॉक-आधारित का उपयोग नहीं कर रहे हैं।
Crashalot

जब आप पर्यवेक्षक को हारने के लिए पर्यवेक्षकों को छोड़ देते हैं तो क्या वे पर्यवेक्षकों को हटा देते हैं? और जब आप स्टोरीबोर्ड का उपयोग किए बिना प्रोग्राम से एक वर्ग से दूसरे प्रोग्राम में जा रहे हैं, तो क्या यह काम नहीं करता है?
सिरिल

21

स्विफ्ट 4.2 में, यह एक तरीका है जिससे आप पर्यवेक्षक को हटा सकते हैं

deinit {
    NotificationCenter.default.removeObserver(self, name: Notification.Name.Identifier, object: nil)
}

viewDidLoad वर्ग में सेटअप addObserver अधिसूचना

override func viewDidLoad() {
    super.viewDidLoad()
    NotificationCenter.default.addObserver(self, selector: #selector(didReceivedItemDetail), name: Notification.Name.Identifier, object: nil)
}

2
ज्ञात हो कि धीमी गति से नेटवर्क की स्थिति और कुछ उपयोगकर्ता गतिविधि के तहत अर्थात व्यस्त दृश्य क्रिया के दौरान दूर हटना संभव नहीं है। मैंने इसे परीक्षणों में देखा है।
गॉर्डनडब्ल्यू

3
@GordonW यदि आपके विचार विधि को आपके विचार नियंत्रक जीवन चक्र के अंत में नहीं कहा जाता है, तो उस कक्षा में स्मृति समस्या है।
दहल


4

मैं यह भी बताना चाहता हूं कि आपको इस विधि का उपयोग करना चाहिए:

func addObserver(_ observer: Any, selector aSelector: Selector, name aName: NSNotification.Name?, object anObject: Any?)

के बजाय

func addObserver(forName name: NSNotification.Name?, object obj: Any?, queue: OperationQueue?, using block: @escaping (Notification) -> Void) -> NSObjectProtocol

उत्तरार्द्ध पर्यवेक्षक को नहीं हटाएगा (हाल ही में इस समस्या में भाग गया)। यदि आप iOS9 का उपयोग कर रहे हैं तो पूर्व पर्यवेक्षक को हटा देगा।


भूतपूर्व पर्यवेक्षक को कब हटाता है?
शुभम


मुझे लगता है कि क्योंकि आपके पास दूसरी विधि में एक चक्र है और पर्यवेक्षक को मैन्युअल रूप से deallocविधि में नहीं निकाला है ।
निक कोव


1

स्विफ्ट 5

मेरे पास एक चैट एप्लिकेशन है, इसलिए जब भी मैं अपने ChatLogViewController से कुछ अन्य व्यू कॉन्ट्रोलर और फिर वापसी पर जाता हूं, तो मेरे पास मेरी कीबोर्ड सूचना का 1 अतिरिक्त ऑब्जर्वर है। इसे हटाने के लिए जब मैं अपना व्यू-कॉन्ट्रोलर बदलता हूं या अपने चैटलॉग व्यू कॉन्ट्रोलर से गायब हो जाता हूं, तो सभी पर्यवेक्षकों को हटा देता हूं ।

override func viewDidDisappear(_ animated: Bool) {    
    super.viewDidDisappear(animated)

    NotificationCenter.default.removeObserver(self)
}

0

यदि आप अपने पर्यवेक्षक को इसमें जोड़ते हैं viewWillAppear()और उन्हें अंदर निकालते हैं तो यह भी अच्छा हैviewWillDisappear()

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.