2012-05-29 10 views
35

मेरे पास एक दृश्य है (हम इस दृश्य को कॉल करेंगे ए) जिसमें weak संपत्ति है इसके पर्यवेक्षण (बी देखें)। एक केवीओ का पर्यवेक्षण देखें, बी देखें। चूंकि ए को देखने के संदर्भ में बी एक कमजोर संपत्ति है (एक बनाए रखने के चक्र को रोकने के लिए), मैं पर्यवेक्षक को कैसे हटा सकता हूं (ए देखरेख बी)? इससे पहले कि मुझे इसे हटाने का मौका मिलने से पहले बी को देखने के लिए ए संदर्भ देखें।आप कमजोर संपत्ति से केवीओ को कैसे हटाते हैं?

एक बी बाद भी जीवित रहता के बाद से दृश्य नियंत्रक ए के लिए एक मजबूत संदर्भ है यहाँ लीक लॉग संदेश है:

An instance 0x9ac5200 of class UITableView was deallocated while key value observers were still registered with it. Observation info was leaked, and may even become mistakenly attached to some other object. Set a breakpoint on NSKVODeallocateBreak to stop here in the debugger. Here's the current observation info: 
<NSKeyValueObservationInfo 0x8660360> (
<NSKeyValueObservance 0x8660320: Observer: 0x8660020, Key path: contentOffset, Options: <New: YES, Old: NO, Prior: NO> Context: 0x8660020, Property: 0x864ac80> 
) 

बी एक UITableView है। NSKVODeallocateBreak पर ब्रेकपॉइंट सेट करना बेकार परिणाम उत्पन्न करता है।

removeFromSuperview में, मैं पर्यवेक्षक को हटाने का प्रयास करता हूं लेकिन बी का संदर्भ बी 0 पहले से ही nil है।

unsafe_unretained पर स्विच करना और दृश्य नियंत्रक के में समस्याएं हल करने के लिए मैन्युअल रूप से या [A removeFromSuperview] पर कॉल करना समस्या हल करती है। मैं जानना चाहता हूं कि weak संपत्ति का उपयोग करके इसे कैसे हल किया जाए।

यहाँ प्रासंगिक कोड है: https://gist.github.com/2822776

+0

मेरा बुरा ... +1 किसी भी तरह। – CodaFi

उत्तर

1

आप एक स्पष्ट कमजोर संपत्ति superview संदर्भित और फिर @"propertyReferringSuperview.propertyOfSuperview" की तरह एक महत्वपूर्ण पथ के साथ self निरीक्षण निर्धारित कर सकते हैं? जब आपको केवीओ अधिसूचना मिलती है, तो आप self.propertyReferringSuperview == nil जांचते हैं और @"propertyReferringSuperview.propertyOfSuperview" देखकर रोकते हैं।

+1

मैंने इस दृष्टिकोण की कोशिश की है। जब पर्यवेक्षक के कमजोर संदर्भ को ढीला कर दिया जाता है, तो केवीओ आग नहीं लगाता है। –

+0

क्या शर्म की बात है ... शायद कस्टम सेटर में सेट अप डालने का प्रयास करें 'setPropertyReferringSuperview: '? मुझे उम्मीद है कि जब कमजोर संदर्भ 'शून्य' हो जाता है तो इसे बुलाया जाता है। दरअसल, आप इस सेटर में सही निरीक्षण करना शुरू कर सकते हैं और रोक सकते हैं। – Stream

+0

यह एक अच्छा जवाब है। पर्यवेक्षक को ढीला होने पर आपको स्वयं को पर्यवेक्षक के रूप में हटाने की आवश्यकता नहीं है। जब तक आप को हटाया नहीं जाता है तब तक आप एक पर्यवेक्षक रह सकते हैं। तो, केवल init में सुनने के लिए पंजीकरण करें (भले ही आपकी संपत्ति शून्य है यह ठीक है), फिर dealloc (या deinit) में पंजीकरण रद्द करें। – plivesey

2

मुझे इस मामले के लिए विशेष रूप से अनावश्यक रूप से आवश्यक किसी भी प्रकार का कोड मिल जाता है क्योंकि हटाने को स्वचालित किया जा सकता है।

एआरसी की शुरूआत के साथ, ऐप्पल को पर्यवेक्षकों को स्वचालित रूप से हटाने की आवश्यकता होनी चाहिए जो इस तरह के मामलों को ठीक करेगी, लेकिन दुर्भाग्य से उन्होंने नहीं किया। https://github.com/krzysztofzablocki/SFObservers मैं समझाया है मैं कैसे है कि अपने ब्लॉग पर प्रबंधन किया:: लेकिन मैं अपने ही वर्ग है कि इस कमी सुविधा जोड़ता बनाया है http://www.merowing.info/2012/03/automatic-removal-of-nsnotificationcenter-or-kvo-observers/

तुम मेरे समाधान को देखें, तो आप, देखेंगे यह सुनिश्चित करें कि मूल बनाता है कोड को बुलाया जाता है, भले ही सेब अन्य लोगों को कॉल करता है, भले ही सेब अपने आंतरिक व्यवहार को बदलता है, फिर भी श्रेणी ठीक काम करेगी :)

+0

आपका एसएफओवी सर्वर अच्छा दिखता है। मैं कम चतुर समाधान का उपयोग करने की उम्मीद कर रहा था। NSObject पर swizzling सामान थोड़ा डरावना है। कौन जानता है कि वे आईओएस 6 में क्या बदलेंगे। –

+0

यही कारण है कि मेरा समाधान मूल तरीकों का कोई भी आदेश नहीं मानता है और इसके बजाय मूल कोड को कॉल करता है :-) तो भविष्य में सबूत अगर वे कुछ भी बदलते हैं। –

0

कमजोर संपत्ति जोड़ने के बजाय, आप केवल superview संपत्ति का उपयोग कर सकते हैं और केवीओ अवलोकन को जोड़ने/निकालने के लिए willMoveToSuperview: लागू करें।

- (void)willMoveToSuperview:(UIView *)newSuperview { 
    [self.superview removeObserver:self forKeyPath:@"contentOffset" context:context]; 
    [newSuperview addObserver:self forKeyPath:@"contentOffset" options:NSKeyValueObservingOptionNew context:context]; 
    [super willMoveToSuperview:newSuperview]; // optional as default implementation does nothing 
} 
+0

जब 'willMoveToSuperview:' कहा जाता है, तो कमजोर संपत्ति संदर्भ बी (या 'Gist में scrollView') संदर्भ में पहले से ही 'nil' है। –

+0

हां लेकिन आपने बताया कि बी बी ए के पर्यवेक्षण है। इसलिए आपको 'scrollView' प्रॉपर्टी की आवश्यकता नहीं है। बस 'पर्यवेक्षण' का प्रयोग करें। –

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