2009-05-28 14 views
174

मैं स्कॉट स्टीवंसन द्वारा बनाए गए अद्भुत ब्लॉग के माध्यम से सर्फिंग कर रहा हूं, और मैं 'असाइन' संपत्ति बनाम 'बनाए रखने' प्रतिनिधियों को असाइन करने की मौलिक उद्देश्य-सी अवधारणा को समझने की कोशिश कर रहा हूं। ध्यान दें, दोनों कचरा एकत्रित वातावरण में समान हैं। मैं ज्यादातर गैर-जीसी आधारित पर्यावरण से संबंधित हूं (उदाहरण: आईफोन)।ऑब्जेक्टिव-सी प्रतिनिधियों को आम तौर पर बनाए रखने के बजाय संपत्ति असाइनमेंट क्यों दिया जाता है?

स्कॉट ब्लॉग से

सीधे:।

"असाइन कीवर्ड एक सेटर जो सीधे उदाहरण चर के लिए मूल्य प्रदान करती है, बल्कि कॉपी करने या इसे बनाए रखने की तुलना में उत्पन्न होगा यह सबसे अच्छा NSInteger और CGFloat, या की तरह आदिम प्रकार के लिए है ऑब्जेक्ट्स जो आप सीधे नहीं हैं, जैसे प्रतिनिधियों। "

इसका क्या अर्थ है कि आप सीधे प्रतिनिधि वस्तु का मालिक नहीं हैं? मैं आम तौर पर अपने प्रतिनिधियों को बरकरार रखता हूं, क्योंकि यदि मैं नहीं चाहता कि वे अस्थियों में चले जाएं, तो मेरे लिए इसका ख्याल रखना होगा। मैं आमतौर पर अमूर्त UITableViewController अपने संबंधित डेटा स्रोत और प्रतिनिधि से दूर भी। मैं उस विशेष वस्तु को भी बरकरार रखता हूं। मैं यह सुनिश्चित करना चाहता हूं कि यह कभी नहीं चलेगा इसलिए मेरे UITableView के पास हमेशा इसके प्रतिनिधि हैं।

क्या कोई और बता सकता है कि मैं कहां/क्यों गलत हूं, इसलिए मैं बनाए रखने के बजाए प्रतिनिधियों पर असाइन संपत्ति का उपयोग करने के उद्देश्य-सी 2.0 प्रोग्रामिंग में इस सामान्य प्रतिमान को समझ सकता हूं?

धन्यवाद!

+0

"प्रतिनिधियों" के साथ और "आईफोन" के बिना retagged। –

+0

प्रतिलिपि के बजाय प्रतिनिधि असाइन क्यों है (जैसे एनएसएसटींग?) – OMGPOP

उत्तर

174

कारण आप से बचने कि प्रतिनिधियों को बनाए रखना है कि आप एक बनाए रखने के चक्र से बचने की जरूरत है:

एक बी एक बी के प्रतिनिधि के रूप में सेट बनाता है ... एक उसके मालिक द्वारा जारी की है

बी हैं ए को बनाए रखा था, ए जारी नहीं किया जाएगा, क्योंकि बी बी का मालिक है, इस प्रकार ए का डेलोक कभी नहीं बुलाया जाएगा, जिससे ए और बी दोनों रिसाव के कारण हो सकता है।

आपको ए जाने के बारे में चिंता नहीं करनी चाहिए क्योंकि यह बी का मालिक है और इस प्रकार इसे डेलोक में छुटकारा पाता है।

+0

मैं सहमत नहीं हूं, माइक। मुझे बस एक समस्या मिली जहां एक मॉडल के पास एक प्रतिनिधि होता है जो मोडल को खारिज कर देता है। लेकिन जब मैं मोडल में स्मृति चेतावनी करता हूं, तो यह प्रतिनिधि को जारी करता है। फिर जब मैं अपना मोडल बर्खास्त करने जाता हूं, तो प्रतिनिधि शून्य होता है। दुर्घटना। –

+0

ठीक है तो मैं असहमत हूं, लेकिन आप सही हैं कि यह एक डिज़ाइन दोष है। मुझे पता चला कि मैं असली बर्खास्तगी के एक बच्चे वर्ग के माध्यम से अपनी बर्खास्तगी कॉल पर जा रहा था। उस बच्चे वर्ग को रिहा कर दिया गया और खारिज करने के लिए मोडल के कंटेनर प्रतिनिधि को पास नहीं किया जा सका। मैंने इसे अंतिम प्रतिनिधि को पॉइंटर पर पास करने के लिए बदल दिया और उसे स्मृति चेतावनी में रिहा नहीं किया गया और सब अच्छा है। –

+2

आपका कोड इस तरह से कभी भी लिखा नहीं जाना चाहिए कि एक शून्य प्रतिनिधि इसे क्रैश कर देता है। केवल स्वामित्व वाली वस्तु का स्वामित्व संदर्भ होना चाहिए। जब dealloc'd, इसे स्वामित्व वाली वस्तुओं के प्रतिनिधियों को उन्हें जारी करने से पहले शून्य करने के लिए सेट करना होगा। फिर शून्य प्रतिनिधि को भेजे गए किसी भी संदेश को अनदेखा कर दिया जाता है। हालांकि, एक संदेश में एक शून्य ऑब्जेक्ट * पास करना क्रैश हो सकता है। बस सुनिश्चित करें कि आप इस तरह से प्रतिनिधियों से सौदा नहीं करते हैं। –

44

क्योंकि प्रतिनिधि संदेश भेजने वाली वस्तु प्रतिनिधि के स्वामित्व में नहीं है।

कई बार, यह एक और तरीका है, जब एक नियंत्रक स्वयं को दृश्य या खिड़की के प्रतिनिधि के रूप में सेट करता है: नियंत्रक दृश्य/विंडो का मालिक होता है, इसलिए यदि व्यू/विंडो के प्रतिनिधि का स्वामित्व होता है, तो दोनों ऑब्जेक्ट्स होंगे एक दूसरे का मालिकाना यह, ज़ाहिर है, एक बरकरार चक्र है, एक ही परिणाम के साथ एक रिसाव के समान (वस्तुओं जो मृत जीवित रहना चाहिए)।

अन्य बार, वस्तुएं सहकर्मी हैं: न तो कोई दूसरा का मालिक है, संभवतः क्योंकि वे दोनों एक ही तीसरे वस्तु के स्वामित्व में हैं।

किसी भी तरह से, प्रतिनिधि के साथ वस्तु को अपने प्रतिनिधि को बनाए रखना नहीं चाहिए।


परिशिष्ट (कम से कम एक अपवाद के माध्यम से। मुझे याद है नहीं कि यह क्या था, और मुझे नहीं लगता कि इसके लिए एक अच्छा कारण नहीं था।, नहीं है) (जोड़ा गया 2012-05-19): एआरसी के तहत, आपको assign के बजाय weak का उपयोग करना चाहिए। ऑब्जेक्ट मरने पर कमजोर संदर्भ nil पर स्वचालित रूप से सेट हो जाते हैं, जिससे संभावना है कि प्रतिनिधि वस्तु मृत प्रतिनिधि को संदेश भेज देगी।

यदि आप किसी कारण से एआरसी से दूर रह रहे हैं, तो कम से कम assign गुणों को बदलें जो unsafe_unretained पर ऑब्जेक्ट्स को इंगित करते हैं, जो स्पष्ट करते हैं कि यह किसी ऑब्जेक्ट के लिए एक अप्रत्याशित लेकिन गैर-शून्य संदर्भ है।

assign एआरसी और एमआरसी दोनों के तहत गैर-ऑब्जेक्ट मूल्यों के लिए उपयुक्त रहता है।

+13

'NSURLConnection' अपने प्रतिनिधि को बरकरार रखता है। –

+0

हां, 'कमजोर' का उपयोग करें, लेकिन यह मूल प्रश्न का उत्तर नहीं देता है: ऐप्पल 'कमजोर' के बजाय 'असाइन' का उपयोग क्यों करता है? – wcochran

+0

@wcochran: मूल प्रश्न यह था कि "रखरखाव * के बजाए प्रतिनिधि गुणों को 'असाइनमेंट' क्यों दिया जाता है; जब पूछा गया तो 'कमजोर' अस्तित्व में नहीं था। आपका प्रश्न एक अलग है, जिसे आपको अलग से पूछना चाहिए। मुझे इसका जवाब देने में खुशी होगी। –

17

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

+0

"ध्यान दें कि जब आपके पास एक प्रतिनिधि होता है जो असाइन करता है, तो जब भी ऑब्जेक्ट को हटाया जा रहा है, तो हमेशा उस प्रतिनिधि मूल्य को शून्य पर सेट करना बहुत महत्वपूर्ण हो जाता है" क्यों? –

+2

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

+1

यह केवल तभी जरूरी है जब आप जिस ऑब्जेक्ट के प्रतिनिधि हैं, उसे टाइमर या अन्य एसिंक्रोनस कॉलबैक जैसे किसी अन्य स्रोत द्वारा बनाए रखा जा रहा है। अन्यथा, इसे रिलीज़ करने के बाद इसे हटा दिया जाएगा और प्रतिनिधि विधियों को कॉल करने की कोशिश नहीं की जाएगी। –

1

इसके पीछे एक कारण चक्र बनाए रखने से बचने के लिए है। बस उस परिदृश्य से बचने के लिए जहां ए और बी दोनों ऑब्जेक्ट एक-दूसरे को संदर्भित करते हैं और उनमें से कोई भी स्मृति से मुक्त नहीं होता है।

Acutally असाइन करें एनएसआईएनटेगर और सीजीएफलोट, या ऑब्जेक्ट्स जैसे कि आप सीधे नहीं हैं, जैसे कि प्रतिनिधि नहीं हैं।

+0

यह ओपी के उद्धरण और स्वीकार किए गए उत्तर से क्रमशः कॉपी किया गया है, है ना? – dakab

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