2010-02-18 11 views
5

निम्नलिखित संपत्ति परिभाषा को देखते हुए:ऑब्जेक्टिव-सी गुण और मेमोरी मैनेजमेंट

self.foo = [[MyObject alloc] init]; 

:

@property (nonatomic,retain) MyObject* foo; 

निम्नलिखित कोड एक स्मृति रिसाव के कारण होता है?

ऐसा लगता है कि alloc कॉल में जुड़ जाता है जैसे 1 के लिए वस्तु पर गिनती बनाए रखने, तो बनाए रखने के अंदर संपत्ति सेटर 1. लिए अपना बजट बढ़ा लेकिन चूंकि प्रारंभिक गिनती 0 को कम कर कभी नहीं किया जाता है, तब भी जब वस्तु रहेंगे स्वयं जारी किया जाता है। क्या यह विश्लेषण सही है?

यदि हां, तो ऐसा लगता है जैसे मैं दो विकल्प है दिखता है:

self.foo = [[[MyObject alloc] init] autorelease]; 

जो प्रदर्शन कारणों से iPhone पर अनुशंसित नहीं है, या:

MyObject* x = [[MyObject alloc] init]; 
self.foo = x 
[x release]; 

जो थोड़ा बोझिल है। क्या अन्य विकल्प हैं?

उत्तर

2

आप ठीक कह रहे हैं, self.foo = [[MyObject alloc] init]; स्मृति लीक कर रहा है। दोनों विकल्प सही हैं और इस्तेमाल किया जा सकता है। इस तरह के बयान में autorelease के बारे में: ध्यान रखें कि जैसे ही वर्तमान रन लूप समाप्त होता है, ऑब्जेक्ट ऑटोरेलीज पूल द्वारा जारी किया जाएगा, लेकिन इसे शायद self तक बहुत अधिक समय तक बनाए रखा जाएगा, इसलिए स्मृति उपयोग के साथ कोई समस्या नहीं है यहाँ spikes।

3

क्या कोई विकल्प हैं?

सं

आप में सक्षम लिखने autorelease का उपयोग करने और कोको टच पुस्तकालय उन्हें कई स्थानों में उपयोग करता है बिना एक iPhone आवेदन के ज्यादा होने के लिए नहीं जा रहे हैं। समझें कि यह क्या कर रहा है (अगले फ्रेम पर हटाने के लिए पॉइंटर जोड़ना) और तंग लूप में इसका उपयोग करने से बचें।

आप MyObject पर क्लास विधि का उपयोग कर सकते हैं जो इसे साफ़ करने के लिए alloc/init/autorelease करता है।

-(id)init { 
    if (self = [super init]) { 
     self.someObject = [[[Object alloc] init] autorelease]; 
    } 
    return self; 
} 

-(void)dealloc { 
    [someObject release]; 
    [super dealloc]; 
} 

autorelease विज्ञप्ति संदर्भ:

+ (MyObject *)object { 
    return [[[MyObject alloc] init] autorelease]; 
} 

self.foo = [MyObject object]; 
+0

यह एक शानदार विकल्प है जो उदाहरण बनाते समय समय बचाता है। –

3

iPhone पर एक बनाए रखा संपत्ति का प्रबंधन करने के लिए सबसे आसान तरीका है (autorelease के रूप में बुरा के रूप में आपको लगता है, कम से कम सबसे उपयोगों के लिए नहीं है) निम्नलिखित है फ़्लोटिंग इंस्टेंस को जो self.object को सौंपा गया है जो आपके संदर्भ को बरकरार रखता है, आपको एक संदर्भ के साथ छोड़ देता है (someObject)। फिर जब वर्ग नष्ट हो जाता है तो वस्तु को नष्ट करने, केवल शेष संदर्भ जारी किया जाता है।

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

+(Object)object; 
+(Object)objectWithCount:(int)count; 
+(Object)objectFromFile:(NSString *)path; 

एक निर्धारित कर सकते हैं इन के रूप में:

// No need to release o if fails because its already autoreleased 
+(Object)objectFromFile:(NSString *)path { 
    Object *o = [[[Object alloc] init] autorelease]; 
    if (![o loadFromFile:path]) { 
     return nil; 
    } 
    return o; 
} 
+0

-1 '[सुपर इनिट]' और न ही 'सुपर डेलोक]' को कॉल करने के लिए, जो खतरनाक है। – MrMage

+0

मेरी गलती, मैं केवल कुछ ऑब्जेक्ट असाइनमेंट विधि को इंगित कर रहा था। कोड अपडेट किया गया। –

+0

यह अभी भी गलत है, वास्तव में 'init' विधि में '[सुपर init]' के 'वापसी' के रिटर्न मान को असाइन करना शामिल है। – dreamlax

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