2011-03-23 11 views
7

मैं कोको/उद्देश्य-सी के लिए नया हूं और मैं अपनी वस्तुओं के रिलीज के साथ struggeling हूँ।किसी ऑब्जेक्ट को फोरीन लूप में कैसे रिलीज़ करें?

gastroCategoryList = [[NSMutableArray alloc] init]; 
for (NSDictionary *gastrocategory in gastrocategories) { 
    NSString *oid = [gastrocategory objectForKey:@"id"]; 
    GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:@"name"]]; 
    [gastroCategoryList addObject:gc]; 
} 

विश्लेषक मुझे पता चलता है कि "gastrocategory के लिए" के रूप में परिभाषित एक संभावित स्मृति रिसाव है: मैं निम्नलिखित कोड है। लेकिन मुझे यकीन नहीं है कि क्या मैं इसे लूप के अंत में रिलीज़ कर सकता हूं?

निम्नलिखित कोड पर भी

:

- (NSArray *)eventsForStage:(int)stageId { 

    NSMutableArray *result = [[NSMutableArray alloc] init]; 

    for (Event *e in eventList) { 
     if ([e stageId] == stageId) { 
      [result addObject:e]; 
     } 
    } 

    return result; 
} 

विश्लेषक मुझसे कहता है कि मेरी "परिणाम" एक संभावित रिसाव है। लेकिन मुझे इसे कहां छोड़ देना चाहिए?

क्या मुझे याद रखने के लिए एक सरल नियम भी है जब मुझे @property पर असाइन, कॉपी, बनाए रखने आदि का उपयोग करना चाहिए?

एक और समस्या:

- (IBAction)showHungryView:(id)sender { 
    GastroCategoriesView *gastroCategoriesView = [[GastroCategoriesView alloc] initWithNibName:@"GastroCategoriesView" bundle:nil]; 

    [gastroCategoriesView setDataManager:dataManager]; 

    UIView *currentView = [self view]; 
    UIView *window = [currentView superview]; 

    UIView *gastroView = [gastroCategoriesView view]; 

    [window addSubview:gastroView]; 

    CGRect pageFrame = currentView.frame; 
    CGFloat pageWidth = pageFrame.size.width; 
    gastroView.frame = CGRectOffset(pageFrame,pageWidth,0); 

    [UIView beginAnimations:nil context:NULL]; 
    currentView.frame = CGRectOffset(pageFrame,-pageWidth,0); 
    gastroView.frame = pageFrame; 
    [UIView commitAnimations]; 

    //[gastroCategoriesView release]; 
} 

मैं समझ नहीं है, "gastroCategoriesView" एक संभावित रिसाव है। मैंने इसे अंत में या ऑटोरेलीज़ के साथ रिलीज़ करने की कोशिश की लेकिन न तो ठीक काम करता है। हर बार जब मैं अपना ऐप समाप्त कर रहा हूं तो विधि को कॉल करता हूं। आपको पुन: बहुत धन्यवाद!

उत्तर

9

अपने पाश में, सूची में इसे अब और जोड़ने के बाद आप अपने पाश दायरे में इसकी आवश्यकता नहीं होगी के बाद प्रत्येक gc जारी:

gastroCategoryList = [[NSMutableArray alloc] init]; 
for (NSDictionary *gastrocategory in gastrocategories) { 
    NSString *oid = [gastrocategory objectForKey:@"id"]; 
    GastroCategory *gc = [[GastroCategory alloc] initWithId:[oid intValue] name:[gastrocategory objectForKey:@"name"]]; 
    [gastroCategoryList addObject:gc]; 
    [gc release]; 
} 

अपने विधि में, result घोषित के स्वामित्व दोषमुक्त करने के लिए autoreleased जा करने के लिए यह आपके विधि से:

NSMutableArray *result = [[[NSMutableArray alloc] init] autorelease]; 

// An alternative to the above, produces an empty autoreleased array 
NSMutableArray *result = [NSMutableArray array]; 

संपादित करें: अपने तीसरे अंक में, आप अपने दृश्य नियंत्रक क्योंकि इसके दृश्य खिड़की के द्वारा प्रयोग किया जा रहा है प्रदर्शन नहीं करते। इसे ऑटोरेलीज़ में सेट करने से भी वही भाग्य होता है, केवल देरी हो जाती है।

आपको कहीं अपने GastroCategoriesView नियंत्रक को बनाए रखना होगा, उदा। आपके ऐप प्रतिनिधि के एक उदाहरण चर में।

+0

आपको बहुत बहुत धन्यवाद। क्या आप @property समस्या के लिए एक नियम भी जानते हैं? – n3on

+0

@ n3on: अगर किसी संपत्ति को 'रखरखाव' या 'प्रतिलिपि' घोषित किया जाता है, तो आपको अपनी कक्षा की 'डेलोक' विधि में अपना ivar जारी करना चाहिए। – BoltClock

+0

@ बोल्टक्लॉक: ठीक है धन्यवाद। लेकिन मुझे प्रतिलिपि का उपयोग कब करना चाहिए, बनाए रखना चाहिए या असाइन करना चाहिए? – n3on

1

गैस्ट्रो श्रेणी सूची में जोड़े जाने के बाद जीसी जारी करने का कारण यह है कि जब किसी ऑब्जेक्ट को किसी सरणी में जोड़ा जाता है, तो सरणी उस ऑब्जेक्ट को बरकरार रखती है। तो, भले ही आप अपना जीसी जारी करते हैं, फिर भी यह चारों ओर होगा; गैस्ट्रो श्रेणीसूची द्वारा बनाए रखा।

जब आप किसी विधि से नव निर्मित ऑब्जेक्ट लौट रहे हैं, तो आपको autorelease. पर कॉल करने की आवश्यकता है, यह ऑब्जेक्ट को रिलीज़ करने के बाद केवल कॉलटाइम कॉलिंग के दायरे को छोड़ने के बाद ऑब्जेक्ट को रिलीज़ करने का कारण बनता है, जिससे कॉलिंग विधि को करने का मौका मिलता है लौटा मूल्य के साथ कुछ।

ध्यान दें कि यदि आपकी विधि शब्द प्रतिलिपि या नई के साथ शुरू होती है, तो आपको अपने ऑब्जेक्ट को स्वतः नहीं करना चाहिए; आपको इसे रिलीज करने के लिए कॉलिंग विधि के लिए छोड़ देना चाहिए।

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

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

यह भी ध्यान रखें कि आपको गैर-ऑब्जेक्ट प्रकारों जैसे int के लिए असाइन करना होगा।

मेमोरी Management Programming Guide बिट के माध्यम से पढ़ें; यह काफी उपयोगी है।

3

बोल्टक्लॉक का जवाब आपके प्रश्न के पहले भाग के रूप में स्पॉट-ऑन है। मैं बाकी से निपटने की कोशिश करूंगा।

असाइन सरल, गैर-ऑब्जेक्ट प्रकारों जैसे int, double, या struct के लिए है। यह एक सेटर उत्पन्न करता है जो एक सादा पुराना असाइनमेंट करता है, जैसा कि "foo = newFoo" में है। & कॉपी करें, क्योंकि उनके नामों का अर्थ है, या तो नए मान ("foo = [newFoo copy]") की एक प्रति बनाएं या इसे बनाए रखें ("foo = [newFoo retain]")। दोनों मामलों में, सेटर पुराने मान को उचित के रूप में जारी करेगा।

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

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

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

+0

ऐसे समय होते हैं जब आपको ऑब्जेक्ट प्रकारों पर असाइन करने की आवश्यकता होती है। यह न केवल ऑब्जेक्ट प्रकारों के लिए है। – GendoIkari

+0

सच - कुछ नामों के लिए चक्र, प्रतिनिधि, और जुड़े आईबीओटलेट बनाए रखें। मैं इसे सरल रखने की कोशिश कर रहा था, लेकिन थोड़ा सा * बहुत * सरल हो सकता था। –

+0

मैंने हमेशा आईबीओटलेट बनाए रखा है ... क्या कोई कारण है कि उन्हें असाइन किया जाना चाहिए? क्या वे आपके स्वयं के नियंत्रक वर्ग के अलावा किसी अन्य चीज़ से बनाए गए हैं? – GendoIkari

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

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