2010-06-28 9 views
5

मैं एक व्यापक जावा पृष्ठभूमि के साथ एक आईफोन/उद्देश्य-सी नौसिखिया हूं।एनएसएमयूटेबलएरे ऐरेविथ कैपेसिटी बनाम initWithCapacity

मैं में ऑब्जेक्टिव-सी स्मृति प्रबंधन के बारे में अधिक सीख रहा हूँ और मैं मेमोरी मैनेजमेंट पर एप्पल के प्रलेखन पढ़ रहा हूँ: http://developer.apple.com/iphone/library/documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html

वस्तु स्वामित्व नीति खंड में, यह कहता है कि आप आप एक के माध्यम से बनाए गए किसी भी वस्तु के मालिक हैं विधि जो आवंटन से शुरू होती है, नई या प्रतिलिपि होती है। स्वामित्व का तात्पर्य यह है कि जब आप इसके साथ काम करते हैं तो आपको स्पष्ट रूप से release ऑब्जेक्ट की आवश्यकता होती है।

तो मैं NSMutableArray प्रलेखन पर देख रहा हूँ: http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSMutableArray_Class/Reference/Reference.html

दो तरीकों कि काफी एक ही बात कर रहे हैं ... वे दोनों कुछ आरंभिक क्षमता के साथ एक सरणी पैदा करते हैं। एक वर्ग विधि है और दूसरा एक उदाहरण विधि है।

+ (id)arrayWithCapacity:(NSUInteger)numItems; 
- (id)initWithCapacity:(NSUInteger)numItems; 

अब, आलसी जावा डेवलपर मैं कर रहा हूँ जा रहा है यही कारण है कि मैं कभी भी वर्ग विधि कुछ बिंदु पर जानते हुए भी कि समय मैं अपने आप को करने के बाद साफ करने के लिए है में से अधिक उदाहरण विधि का चयन होगा?

मुझे लगता है कि मुझे यहां एक मौलिक बिंदु याद आ रहा है ... क्या यह निर्धारित करने का मामला है जब ऑब्जेक्ट जारी किया जाता है? उदाहरण विधि में autorelease वर्ग विधि बनाम release में? मुझे लगता है कि बहुत सीमित संसाधनों (आईफोन) वाले प्लेटफॉर्म पर मुझे कक्षा विधि का उपयोग करने से रोकना चाहिए और जैसे ही मैं इसके साथ काम कर रहा हूं, वस्तु को छोड़ देना चाहिए?

धन्यवाद!

उत्तर

9

आप आमतौर पर वर्तमान विधि के जीवन से अधिक के लिए ऑब्जेक्ट के मालिक होने के आधार पर चयन करेंगे या नहीं, उदाहरण के लिए, इसे कुछ स्थिर या सीधे ivar को असाइन करें)। उस स्थिति में, आप आवंटन/init विधि का उपयोग कर सकते हैं क्योंकि आप जानते हैं कि आप इसे पहले से ही रखना चाहते हैं। यदि आप केवल वर्तमान विधि के दायरे के लिए इसका उपयोग करने की योजना बना रहे हैं, या आप इसे किसी संपत्ति की तरह प्रबंधित करने के लिए असाइन कर रहे हैं, तो आप शायद सुविधा विधि का उपयोग करेंगे।

जब आप जानते हैं कि आप किसी ऑब्जेक्ट का मालिक बनने जा रहे हैं, तो आवंटन/इनिट कॉल सुविधा/रखरखाव के तरीके से हमेशा अधिक कुशल होता है क्योंकि बाद में ऑब्जेक्ट को मूल रूप से आवंटित/init/autorelease करने की आवश्यकता होती है और फिर जब आप वापस आते हैं तो इसे बनाए रखें।

आप लूप में आवंटित होने पर प्रत्यक्ष आवंटन/इनिट विधियों का भी उपयोग कर सकते हैं और एक ऑटोरेलीज पूल से निपटने की आवश्यकता नहीं है।

+0

क्या यह अब सत्य है कि हमारे पास स्वचालित संदर्भ गिनती है? ऐसा लगता है कि दो विधियों को अब काफी समान होना चाहिए क्योंकि एआरसी कोड मूल रूप से आवंटित/init निर्मित ऑब्जेक्ट में एक अंतर्निहित autorelease लागू होता है। यह देखेगा कि ज्यादातर मामलों में हमें सुविधा विधियों का उपयोग करना चाहिए यदि यह सादगी और स्पष्टता के लिए मौजूद है क्योंकि कोई भी प्रदर्शन दंड नहीं है, अगर मैं इसे सही ढंग से समझता हूं। – Mike

0

इस मामले मैं निम्नलिखित नियमों का पालन करने के लिए संबंधित स्मृति (== "बहुत बुरा") कीड़े से बचने की कोशिश में:

  • यदि आप एक पैरामीटर के रूप में है कि सरणी से गुजर रहे हैं, तो आप उपयोग कर सकते हैं कारखाने विधि कोई समस्या नहीं है, क्योंकि यह स्वीकार करने समारोह बनाए रखने के लिए की जिम्मेदारी है/यह
  • रिलीज आप अंत
6

arrayWithCapacity पर, वस्तु के साथ काम कर रखने के प्रारंभ विधि का उपयोग करें और जारी वस्तु करना चाहते हैं: पहले से ही ऑटोरेलीज लागू है।

initWithCapacity: स्पष्ट रूप से बनाए रखा गया है और आपको इसे स्वयं जारी करने की आवश्यकता होगी। चूंकि आप इसे आमतौर पर [[ए alloc] init के रूप में कहते हैं ...], यह एक लाइटबुल ट्रिगर करेगा "मुझे इसके लिए स्मृति का प्रबंधन करने की आवश्यकता है," अन्य समान जादू शब्द "आवंटन" के अलावा "नया" और "प्रतिलिपि" के रूप में आप स्मृति प्रबंधन मार्गदर्शिका में पढ़ते हैं। लेकिन आपके प्रश्न से, ऐसा लगता है कि आप इसके सिद्धांतों को अच्छी तरह से समझते हैं।

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

एक और उदाहरण यह है कि जब आप एनएस डिक्शनरी या एनएसएआरएआरए जैसे संग्रह में कुछ जोड़ते हैं, तो "ऑटो" को ऑटोरेक्लीज फैक्ट्री विधि के साथ बनाया जा सकता है, क्योंकि संग्रह इसे "ले लेता" रखता है। (चीजें जब संग्रह में जोड़ा रखा जाता है, और जब हटाया का विमोचन किया।)

आप तर्क दे सकते हैं कि

Blah *blah = [Blah blahWithSomething]; 
[myMutableArray addObject:blah]; 

टाइप करने के लिए की तुलना में

Blah *blah = [[Blah alloc] initWithSomething]; 
[myMutableArray addObject:blah]; 
[blah release]; 

पहले मामले में, आप बस क्लीनर है एक रिलीज कॉल के बारे में चिंता करने की ज़रूरत नहीं है। नकारात्मकता यह है कि जब आप एक ही रनलोप में कई बार ऐसा करते हैं, तो पहले मामले की मेमोरी पदचिह्न अधिक होती है अगर यह एक अस्थायी/फेंकने वाली सरणी वस्तु है जो रनलोप के अंत में दूर जाती है। लेकिन अगर यह एक छोटी सी वस्तु है जो लूप में नहीं की जाती है और एक सामान्य मामला के रूप में लंबे समय तक बनाए रखा जाता है, तो उनके पैरों के निशान समान होते हैं।

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