2010-07-16 12 views
17

मैंने निम्नलिखित स्निपेट को थोड़ा सा देखा है:alloc + संश्लेषित संपत्ति के साथ init - क्या यह दो से बढ़ने के लिए गिनती बनाए रखने का कारण बनता है?

शीर्षलेख में:

SomeClass *bla; 
@property(nonatomic,retain) SomeClass *bla; 

कार्यान्वयन फ़ाइल में:

@synthesize bla; 

और फिर

self.bla = [[SomeClass alloc] init]; 

मुझे लगता है कि यह असाइनमेंट 'ब्लै' के लिए दो को ऊपर रखता है; एक बार आवंटन/इनिट कॉल के माध्यम से, फिर बनाए रखने के माध्यम से हमने संश्लेषित संपत्ति सेटटर के माध्यम से होने के लिए कहा।

नतीजतन, मैं आमतौर पर इस तरह की अपनी संपत्तियों की घोषणा करता हूं:

शीर्षलेख में:

SomeClass *_bla; // note the underscore 
@property(nonatomic,retain) SomeClass *bla; 

कार्यान्वयन फ़ाइल में:

@synthesize bla = _bla; 

और फिर

_bla = [[SomeClass alloc] init]; 

बशर्ते मेरी प्रारंभिक धारणा सही है - मुझे यह जानने में दिलचस्पी होगी कि ऐसा करने का 'सही' तरीका है, यानी घोषणाओं, प्रारंभिकरण और गुणों के स्मृति प्रबंधन?

+0

लोड करने के माध्यम से किया जाता है, सबसे पहले, स्टैक ओवरफ़्लो में आपका स्वागत है। स्टैक पर करना महत्वपूर्ण चीजों में से एक है उन उत्तरों को स्वीकार करना जो आपके लिए काम करते हैं। उत्तरदाताओं के लिए और अपनी प्रतिष्ठा के लिए यह महत्वपूर्ण है। – smathy

उत्तर

8

हां, आप सही हैं - retain संपत्ति के संश्लेषित सेटटर का उपयोग करके आपके द्वारा पहले से मौजूद एक उदाहरण पर रीफ-गिनती बढ़ेगी (alloc स्वामित्व का तात्पर्य है)।

बस दूसरा रूप है कि आप अपने initializers में उल्लेख किया है के साथ जाना:

_bla = [[SomeClass alloc] init]; 

... और नहीं तो बनाए रखने गिनती ठीक करने के लिए, उदाहरण के लिए याद रखें:

self.bla = [[[SomeClass alloc] init] autorelease]; 
8

मैं इस बारे में सोच है कि असाइनमेंट 'ब्लै' के लिए दो को ऊपर रखता है;

यह सच है।

मैं है कि क्या वहाँ 'सही' जिस तरह से इस

आपका कोड के अंतिम टुकड़ा करने के लिए सुनने के लिए दिलचस्पी होगी सही तरीका है, लेकिन प्रमुख अंडरस्कोर अनुशंसित नहीं है। संपत्ति और इवर एक ही नाम साझा कर सकते हैं। बस

@interface Foo : Bar { 
    SomeClass* bla; 
} 
@property (nonatomic, retain) SomeClass* bla; 
@end 

@implementation Foo 
@synthesize bla; 
-(id)init { 
    ... 
    bla = [[SomeClass alloc] init]; 
    ... 
} 
-(void)dealloc { 
    [bla release]; 
    ... 
    [super dealloc]; 
} 

पर्याप्त है।


कुछ लोगों

SomeClass* foo = [[SomeClass alloc] init]; 
self.bla = foo; 
[foo release]; 

या

self.bla = [[[SomeClass alloc] init] autorelease]; 
-init विधि में

उपयोग कर सकते हैं, लेकिन मैं दृढ़ता से यह हतोत्साहित , के रूप में यह अनावश्यक रूप से कई तरीकों कहता है, and you cannot guarantee the behavior of the setter

+0

वाओ - स्टैक ओवरफ्लो पर मेरी पहली पोस्ट, और दो उत्तरों 5 मिनट के भीतर। आप दोनों को धन्यवाद! – patschiboy

+6

आप जिन दो पैटर्नों को दृढ़ता से हतोत्साहित करते हैं वे ज्यादातर मामलों में पूरी तरह से स्वीकार्य और सामान्य हैं। आपके द्वारा लिंक किया गया उत्तर ** init ** और 'dealloc' विधियों में ऑब्जेक्ट्स सेट करने के लिए एक्सेसर्स का उपयोग करने के लिए ** ** से संबंधित है। हर जगह, एप्पल की सिफारिश हमेशा एक्सेस चर का उपयोग करने के लिए एक्सेसर्स का उपयोग करना है। – JeremyP

+0

जेरेमीपी सही है, और इसी कारण से इसे सही उत्तर नहीं माना जाना चाहिए। – Felixyz

3

ऐसा लगता है कि यहां कोर समस्या कोको में ऑब्जेक्ट स्वामित्व अर्थशास्त्र की गलतफहमी है। प्रत्येक init, copy या retain किसी ऑब्जेक्ट पर कॉल करने के लिए release या autorelease पर कॉल किया जाना चाहिए। यहां क्या हो रहा है कि init पर कॉल release या autorelease पर मेल खाने वाला कॉल नहीं है।

मुझे लगता है कि यहां भ्रमित करने वाला यह है कि संपत्ति असाइनमेंट के लिए डॉट-नोटेशन एक विधि कॉल के लिए वाक्य रचनात्मक चीनी है। तो ऐसा लगता है कि यह केवल एक असाइनमेंट है जब वास्तविकता में यह एक संपत्ति सेटर के लिए एक कॉल है।

bla = [[SomeClass alloc] init]; 

पूर्व में तब्दील हो:

[self setBla: [[SomeClass] alloc] init]]; 

जबकि बाद सचमुच एक काम है

self.bla = [[SomeClass alloc] init]; 

एक ही बात के रूप में नहीं है।

आपकी समस्या का समाधान करने के लिए सभी तुम सच में यह सुनिश्चित करने की जरूरत है कि कोड है कि init कॉल autorelease कॉल ताकि बनाए रखने गिनती सेटर द्वारा retain कॉल के बाद कम कर दिया जाएगा।

-3

कोई डबल गिनती नहीं है। संश्लेषण द्वारा बनाए गए सेटटर को बनाए रखने से पहले एक रिलीज करता है। सेब वेबसाइट पर संदर्भित अनुसार उद्देश्य सी कक्षा 3 पर स्टैनफोर्ड कक्षा देखें। यह ध्यान देने योग्य भी है कि iboutlets के मामले में आवंटन init की आवश्यकता नहीं है क्योंकि यह xib फ़ाइल

+0

गलत होने के लिए वोट दिया गया। [[xxx alloc] init] एक ऑब्जेक्ट को 1 की बरकरार रखने के साथ देता है, जिसे किसी बिंदु पर प्रतिबिंबित किया जाना चाहिए। यदि आप परिणाम को एक बनाए रखा संपत्ति में संग्रहीत करते हैं, तो तुरंत रखी गई संपत्ति को शून्य पर सेट करें, आपको मेमोरी लीक मिल गई है। – gnasher729