2011-12-19 7 views
14

संपादित किया गया है: शीर्षक बदल दिया गया है। मैं इसे समय में पता नहीं था, लेकिन इस Why am I crashing after MKMapView is freed if I'm no longer using it?MKMapView अभी भी प्रतिनिधि के लिए संदेश भेज रहा है इसके पर्यवेक्षण को


का डुप्लिकेट यह सवाल Why is object not dealloc'ed when using ARC + NSZombieEnabled के समान लेकिन अलग पर्याप्त मैंने सोचा था कि यह वहाँ बाहर फेंकने का मामला किसी में लायक समझता है और मुझे समझा सकता है क्या घटित हो रहा है। दूसरा प्रश्न एक्सकोड बग हो सकता है, इसलिए मुझे लगता है कि यह समान हो सकता है।

परिदृश्य:

  1. RootViewController एक tableView आइटम
  2. एक सेल का चयन का एक समूह प्रदर्शित प्रस्तुत करता है एक मॉडल detailViewController एक और tableView
  3. तालिका सेल की detailViewController में एक युक्त एक MKMapView स्थान दिखा शामिल है आइटम
  4. mapView.delegate = detailViewController
  5. मोडल detailViewController

इसके शीघ्र बाद, एप्लिकेशन बी/MKMapView अब mapView:viewForAnnotation: भेजता ग dealloc'ed detailViewController दुर्घटनाओं को खारिज करें। इस क्रैश को एक उपयोगकर्ता डिवाइस पर विज्ञापन-प्रसार वितरण के साथ पुनर्निर्मित किया गया है, इसलिए इस मुद्दे के पास NSZombieEnabled से कोई लेना देना नहीं है।

मैं जोड़कर दुर्घटना को हल करने में सक्षम था:

_mapView.delegate = nil; 
tableViewCell MapView युक्त dealloc विधि के लिए

प्रश्न: जब सेल को हटा दिया जाता है तो प्रतिनिधि को निपटा देना क्यों जरूरी है? ऐसा लगता है कि mapView को एआरसी द्वारा हटा दिया जाना चाहिए जब सेल को इस अनावश्यक छोड़ने से रोक दिया जाता है। प्रतिनिधियों को नील करना अच्छा अभ्यास है, लेकिन मुझे नहीं लगता था कि इस मामले में इसकी आवश्यकता होगी।

संपादित करें:

@property (nonatomic, strong) MKMapView *   mapView; 

संपादित करें 2:: मैं डॉक्स पढ़ने में बेहतर करने की जरूरत है लगता दोनों detailViewController और UITableViewCells के सभी subviews आला (nonatomic, strong) गुण के रूप में घोषित कर रहे हैं। @fluchtpunkt सही है। यहाँ MKMapView प्रलेखन से प्रासंगिक जानकारी है:

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

+0

क्या आप अपने 'विस्तार दृश्य नियंत्रक' के लिए @ strong/@ कमजोर संपत्ति घोषणाएं पोस्ट कर सकते हैं, खासकर 'एमकेमैप व्यू'? –

+0

किया गया। मेरे पास कोई @weak गुण नहीं है क्योंकि ऐप आईओएस 4.3+ को लक्षित करता है। नक्शा दृश्य एक कस्टम 'UITableViewCell' में एक मजबूत संपत्ति के रूप में है। – XJones

+0

जैसा कि मैंने यहां वर्णित किया है, वही चीज जैसा लगता है: http://stackoverflow.com/questions/2188098/why-am-i-crashing-after-mkmapview-is-freed-if-im-no- लंबे समय से उपयोग करने के लिए यह –

उत्तर

19

MKMapView और की वजह से है कि delegate के लिए संपत्ति अभी भी assign बजाय weak के रूप में घोषित किया जाता है एआरसी के साथ संकलित नहीं है।
MKMapView documentation से:

@property(nonatomic, assign) id<MKMapViewDelegate> delegate 

और Transitioning to ARC Release Notes से:

आप एक dealloc विधि लागू कर सकते हैं यदि आप उदाहरण चर रिहा अलावा अन्य संसाधनों का प्रबंधन करने की जरूरत है। आपको आवृत्ति चर जारी करने की ज़रूरत नहीं है (लेकिन वास्तव में आप नहीं कर सकते हैं), लेकिन आपको सिस्टम कक्षा पर सिस्टम सिस्टम [सिस्टम क्लास इंस्टेंस सेट डिलीगेट: एनआईएल] और एआरसी का उपयोग करके संकलित नहीं किया गया है।


प्रणाली वर्गों के प्रतिनिधियों के लिए (एन एस *, यूआई *) जब आप प्रतिनिधि वस्तु पुनःआवंटन नहीं के बराबर करने के लिए प्रतिनिधियों को स्थापित करने की "पुराने" नियम का उपयोग करने के लिए है।

तो अपने detailViewController

- (void)dealloc { 
    self.mapView.delegate = nil; 
} 
+0

अच्छा, यह है (मैंने) जो मैंने किया था। नक्शा दृश्य एक टेबल सेल में है, इसलिए जब सेल को हटा दिया जाता है तो मैं अब '_mapView.delegate = nil' सेट कर रहा हूं। लेकिन अभी भी थोड़ा संदिग्ध बी/सी लगता है जब मेरे प्रतिनिधिमंडल ('detailViewController') को हटा दिया जाता है, तो 'tableCell' को हटा दिया जाता है जब मेरा कोई नियंत्रण नहीं होता है। ऐसा लगता है कि 'mapView' को हटा दिया जाना चाहिए जब यह सेल पहले से ही dealloc'ed है, तो इसे प्रतिनिधि के लिए सेट करने के लिए फिर से अनावश्यक होना चाहिए, नहीं? – XJones

+0

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

+0

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

0

हालांकि यह सच है कि इस तरह की कक्षाओं के लिए प्रतिनिधियों को स्पष्ट रूप से पहले से ही बहुत देर हो चुकी nil सेट किया जाना चाहिए, dealloc में यह क्या कर रहा है के लिए एक dealloc विधि जोड़ें। viewDidUnload के दौरान आपने पहले ही मानचित्रदृश्य में अपना संदर्भ खो दिया है। आप self.mapView.delegate = nil पहले viewDidUnload (ताकि शायद viewWillDisappear या viewDidDisappear)

मेरे अनुभव से, केवल MKMapView और UIWebView व्यवहार करते हैं इस तरह से करना चाहिए।

+0

जो सही नहीं है। viewDidUnload हमेशा नहीं कहा जाता है। आपको दोनों जगहों पर प्रतिनिधि को निपटाए जाने की जरूरत है। – XJones

+0

भी, इस मामले में यह असंभव है। mapView एक UITableCell में दृश्य नियंत्रक नहीं है। – XJones

+0

मेरा शब्द गलत था लेकिन मैं व्यू कंट्रोलर चक्र चरण के रूप में 'viewDidUnload' के बारे में बात कर रहा था। भले ही 'viewDidUnload' को 'IBOutlets' नहीं कहा जाता है और अन्य कमजोर' UIView' संदर्भ दृश्य पदानुक्रम को अनलोड किए जाने के बाद शून्य हो जाएंगे। (जब तक आप अपने विचारों का एक मजबूत संदर्भ नहीं रखते हैं, जो आपको शायद पहले स्थान पर नहीं करना चाहिए) –