कस्टम डीलॉक और ARC (उद्देश्य-सी)


208

मेरे छोटे iPad ऐप में मेरे पास एक "स्विच भाषा" फ़ंक्शन है जो एक पर्यवेक्षक का उपयोग करता है। हर दृश्य नियंत्रक अपने पर्यवेक्षक के साथ खुद को पंजीकृत करता है viewDidLoad:

- (void)viewDidLoad
{
    [super viewDidLoad];
    [observer registerObject:self];
}

जब उपयोगकर्ता "भाषा बदलें" बटन को हिट करता है, तो नई भाषा मेरे मॉडल में संग्रहीत होती है और पर्यवेक्षक को सूचित किया जाता है और updateUi:अपने पंजीकृत वस्तुओं पर एक चयनकर्ता को बुलाता है ।

यह तब बहुत अच्छी तरह से काम करता है, जब मैं एक TabBarController में नियंत्रकों को देखता हूं। ऐसा इसलिए है क्योंकि जब टैब बार लोड होता है, तो यह अपने चाइल्ड कंट्रोलर से टैब आइकनों को देखे बिना, विचारों को इनिशियलाइज़ किए बिना प्राप्त कर लेता है, इसलिए viewDidLoad:इसे नहीं कहा जाता है, इसलिए उन व्यू कंट्रोलर्स को भाषा परिवर्तन सूचनाएँ नहीं मिलती हैं। इस वजह से, मैंने अपने registerObject:कॉल को initविधि में स्थानांतरित कर दिया ।

जब मैं viewDidLoad:अपने पर्यवेक्षक के साथ पंजीकरण करता था, तो मैं viewDidUnload:अपंजीकृत करता था। चूंकि अब मैं पंजीकरण कर रहा हूं init, इसलिए इसमें अपंजीकृत होने की बहुत अधिक संभावना है dealloc

लेकिन यहाँ मेरी समस्या है। जब मैं लिखता हूं:

- (void) dealloc
{
    [observer unregisterObject:self];
    [super dealloc];
}

मुझे यह त्रुटि मिली:

ARC ने 'डीललोक' का स्पष्ट संदेश भेजने से मना किया

चूंकि मुझे [super dealloc]सुपरक्लास को ठीक से साफ करने के लिए कॉल करने की आवश्यकता है , लेकिन एआरसी मना करता है कि, मैं अब फंस गया हूं। क्या कोई दूसरा तरीका है जब मेरी वस्तु मर रही हो, सूचित किया जाए?


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

मैंने दाएं और बाएं हाथ के विकल्पों के लिए कुछ समान लागू किया। केवल वीसी को संदेश की आवश्यकता होती है जो वर्तमान में प्रदर्शित है। अन्य लोग इंटरफ़ेस में बदलाव करने के लिए viewDidLoad या viewDidAppear में मॉडल को देखते हैं। शायद ऐसा कुछ बेहतर काम करेगा।
डग वॉटकिंस

@BlazejCzapp के बाद से वह एक UITabBarController का उपयोग कर रहा है, और मान लें कि UITabBarController हमेशा पंजीकृत नियंत्रक का संदर्भ रखेगा (जैसा कि मुझे लगता है कि इसके 'बच्चे' नियंत्रकों के साथ मामला है, क्या मेमोरी लीक अभी भी एक मुद्दा होगा? मैं यह नहीं देखता कि पंजीकृत नियंत्रक कब आवंटित किया जाएगा। धन्यवाद
Objectif

जवाबों:


419

एआरसी का उपयोग करते समय, आप बस [super dealloc]स्पष्ट रूप से कॉल नहीं करते हैं - संकलक आपके लिए इसे संभालता है (जैसा कि क्लेंग एलएलवीएम एआरसी दस्तावेज़, अध्याय 7.1.2 में वर्णित है ):

- (void) dealloc
{
    [observer unregisterObject:self];
    // [super dealloc]; //(provided by the compiler)
}

4
यदि दृश्य पर्यवेक्षक के लिए एक संदर्भ रखता है, और पर्यवेक्षक दृश्य का संदर्भ रखता है, तो हमारे पास एक परिपत्र संदर्भ है। इसलिए दृश्य की संदर्भ संख्या 0 से अधिक है, और deallocइसे कभी नहीं कहा जाता है। क्या [observer unregisterObject:self]डीललोक में कॉल करने का कोई मतलब है ? मैं क्या खो रहा हूँ?
user443854

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