سؤال

إليك ممارسة شائعة أراها كثيرًا (بما في ذلك من كتاب مطور iPhone المشهور جدًا)

في ملف .h:

@interface SomeViewController : UIViewController
{
  UIImageView *imgView;
}

في مكان ما في ملف .m:

imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]
applicationFrame]];
[imgView setImage:[UIImage imageNamed:@"someimage.png"]];
[self addSubview:imgView];
[imgView release];

وبعدين نشوف هذا..

- (void) dealloc
{
  [imgView release];
  [super dealloc];

} 

نظرًا لأن imgView يحتوي على تخصيص وإصدار متطابقين، فهل إصدار imgView في Dealloc ضروري؟

أين يتم الاحتفاظ بـ imgView بواسطة استدعاء addSubview؟

هل كانت مفيدة؟

المحلول

نعم، هذا الرمز لديه مشاكل. ذلك <الإضراب> إصدارات imgView في وقت مبكر جدا والتي يحتمل أن تتسبب في حوادث في حالات نادرة يخزن كائن في متغير مثيل دون الاحتفاظ بها، وانه سيكون مجرد عموما حول إدارة الذاكرة بطريقة خاطئة.

واحد الطريقة الصحيحة للقيام بذلك ستكون كما يلي:

@interface SomeViewController : UIViewController
{
    UIImageView *imgView;
}
@property (nonatomic, retain) UIImageView *imgView;

وفي التنفيذ؛

@synthesize imgView;

وفي مكان ما في الوحدة النمطية:

//Create a new image view object and store it in a local variable (retain count 1)
UIImageView *newImgView = [[UIImageView alloc] initWithFrame:self.view.bounds];
newImgView.image = [UIImage imageNamed:@"someimage.png"];

//Use our property to store our new image view as an instance variable,
//if an old value of imgView exists, it will be released by generated method,
//and our newImgView gets retained (retain count 2)
self.imgView = newImgView;

//Release local variable, since the new UIImageView is safely stored in the
//imgView instance variable. (retain count 1)
[newImgView release];

//Add the new imgView to main view, it's retain count will be incremented,
//and the UIImageView will remain in memory until it is released by both the
//main view and this controller. (retain count 2)
[self.view addSubview:self.imgView];

وعلى dealloc لا يزال هو نفسه:

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

نصائح أخرى

الرمز غير صحيح.سوف ينتهي بك الأمر إلى إطلاق سراحك imgView بعد أن تم إلغاء تخصيصها.

في ملف .m الخاص بك، يمكنك:

  1. alloc ذلك --> أنت تملكه
  2. إضافته كمراجعة فرعية -> أنت و UIView يمتلكها
  3. release ذلك --> أنت لا تملكه

ثم في dealloc, ، أنت release imgView على الرغم من أنك لا تملكه، كما أوضحنا في الخطوة 3 أعلاه.عندما تتصل [super dealloc], ، سيحرر العرض جميع طرق العرض الفرعية الخاصة به، وأتصور أنك ستحصل على استثناء.

إذا كنت تريد الاحتفاظ بـ ivar imgView, ، أقترح لا الاتصال release بعد إضافتها كعرض فرعي، والاحتفاظ بها dealloc نفس الشيء.بهذه الطريقة، حتى لو imgView تمت إزالته في مرحلة ما من التسلسل الهرمي للعرض، فسيظل لديك مرجع صالح له.

والرمز غير صحيح، يجب أن لا يكون إطلاقه في طريقة الحرف الأول، فقط عندما يتم استدعاء dealloc (هذا إذا كنت ترغب في الاحتفاظ بها على أنها ايفار، لا تحتاج إلى ما تحتاج مؤشر إلى ذلك في أماكن أخرى منذ addSubview: ستحتفظ الرأي لك)

وأعتقد أن السبب انها لا تحطمها في الواقع لأن لا يزال يتم الاحتفاظ من قبل الطبقة المتفوقة (من الدعوة إلى addSubview :)، لذلك عندما يتم إصداره في dealloc هذا ما متوازنة فعلا. وجهة نظر ربما يزيل نفسه من superview عندما يكون يتم deallocated على الفور بعد ذلك، لذلك عندما يتم استدعاء [super dealloc] انه لم يتم الإفراط في إطلاق سراحهم. هذا هو اعتقادي، في عقد الإيجار.

والإصدار في الحرف الأول غير صحيح.

ولقد ذكرت "ممارسة شائعة" وكتاب اسمه الامم المتحدة. أقترح النظر في الأمثلة الكنسي من أبل: ViewTransitions هو مثال جيد لهذه الحالة (و2 وجهات النظر للتمهيد؛)

http://developer.apple.com/iphone/library /samplecode/ViewTransitions/index.html

(ليس لدي سمعة كافية لذلك أضف تعليق حتى الآن.)

@ بنتفورد:صحح لي إذا كنت مخطئًا، ولكن أعتقد أنه من أجل استخدام أداة الضبط المركبة لخاصية imgView، يجب عليك استخدام "self.imgView":

self.imgView = [[UIImageView alloc] initWithFrame:[[UIScreen mainScreen]

إذا لم يكن لديك الذات., ، إنه يستخدم ivar فقط، ولا يحصل على الاحتفاظ الإضافي.

والجواب الأساسية هي، ينبغي أن يكون هناك فقط [imgView release] واحد في المثال رمز (<م> سواء كان ذلك بعد addSubview أو في dealloc ). ومع ذلك، أود أن إزالة [imgView release] من dealloc وتركه بعد addSubview.

وثمة الصيد على اي فون. مع didReceiveMemoryWarning، هل يمكن أن يكون الكائنات (<م> بما في ذلك عرض كامل ) صدر من تحت لك. إذا كان لديك تطبيق على نطاق الاحتفاظ مجموعة وأنت لا تحترم الذاكرة ثم هل يمكن العثور على التطبيق ببساطة يقتلون.

وخير مثال هو:
إذا كنت تعتقد مجموعة متداخلة من 3 جهات النظر، وعرض 1-> مشاهدة 2-> مشاهدة 3. المقبل، النظر في "viewDidLoad" ويدعو "viewDidUnload. إذا كان المستخدم حاليا في "عرض 3"، فمن الممكن أن التفاصيل view1 تفرغ، وهذا هو المكان الذي تحصل عليه في الملعب.
 إذا كنت تخصيص كائن داخل viewDidLoad ولم الإفراج عنها بعد إضافته إلى subview، ثم لا يتم تحرير الكائن عندما يتم تفريغ التفاصيل view1، ولكن لا يزال تفريغ التفاصيل view1.
 سيتم تشغيل viewDidLoad مرة أخرى وسيتم تشغيل التعليمات البرمجية الخاصة بك مرة أخرى، ولكن الآن كنت قد حصلت على اثنين من التجسيدات من وجوه الخاص بك بدلا من واحدة. سوف كائن واحد يكون في nowhereland بهدف تفريغها من قبل، وسوف الكائن الجديد أن يكون للرأي واضح في الوقت الحالي. شطف، رغوة، وكرر وتجد طلبك تحطمها من تسرب الذاكرة.

في هذا المثال، إذا كانت كتلة معينة من التعليمات البرمجية متقلبة ولديه فرصة ليتم تنفيذها مرة أخرى (<م> سواء بسبب الذاكرة أو وجهة نظر تفريغ )، وأود أن إزالة [imgView release]; من dealloc وترك الأمر بعد addSubView.

وهنا هو وجود صلة على الاحتفاظ المفاهيم الأساسية / الاصدار: http://www.otierney.net/objective-c.html#retain

مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top