سؤال

لقد قرأت عن AutoreleAsepool ولكن هناك نقطة غير واضحة بعض الشيء بالنسبة لي. لدي بعض الوظائف باستخدام مؤشرات الترابط التي تتطلب إدارة الذاكرة المنفصلة باستخدام AutoreleAsepool.

في المثال التالي صحيح

-(void) doSomething {

   NSAutorelease *pool = [[NSAutorelasepool alloc] init];

   NSString *myString = @"Hello";

   [pool release];
}

هل هذا صحيح؟

-(void) doSomething {

   NSAutorelease *pool = [[NSAutorelasepool alloc] init];

   NSString *myString = [[NSString alloc] initWithString:@"Hello"];

   [pool release];
}

أو هذا؟

-(void) doSomething {

   NSAutorelease *pool = [[NSAutorelasepool alloc] init];

   NSString *myString = [[NSString alloc] initWithString:@"Hello"];

   [myString release];
   [pool release];
}

سؤالي هو الكائنات المملوكة التي تم إنشاؤها في نطاق تجمع Autorelease يجب إعادة ربطها على وجه التحديد أو يتم الاعتناء بها عندما يتم إصدار Autorelasepool؟

تيو

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

المحلول

تجمع Autorelease يعالج الكائنات التي تم صدرها. إذا كنت تمتلك كائنًا (عبر تخصيص أو نسخ أو الاحتفاظ) ، فيجب عليك إصداره. لذا فإن مثالك الثاني غير صحيح. كما قمت بتخصيص السلسلة ، فأنت تملكها ويجب أن تصدرها.

يتم إنشاء تجمع Autorelease للخيط الرئيسي. (يمكنك النظر في الوظيفة الرئيسية إذا كنت تريد). كل مؤشر ترابط يحتاج إلى تجمع Autorelease الخاص به لإدارة الكائنات التي تم صدرها التلقائي. لهذا السبب إذا قمت بإنشاء موضوع آخر ، فيجب عليك إنشاء تجمع Autorelease لهذا الموضوع. حتى إذا لم تقم بإنشاء كائن تم إصداره تلقائيًا في مؤشر الترابط ، فيجب عليك إنشاء هذا لأن مكالمات المكتبة في هذا الموضوع قد تنشئ كائنات تم صدر تلقائيًا. حتى إذا كنت متأكدًا من عدم وجود مكالمات مكتبة تقوم بإجراء كائنات تم إنشاؤها التلقائي ، فيجب عليك أيضًا إنشاءها لأن هذه هي أفضل الممارسات ، خاصة إذا كنت تعمل على مشروع كبير تم تطويره وصيانته من قبل العديد من الأشخاص.

نصائح أخرى

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

نظرًا لأن أيا من الكائنات في مثالك يتم توضيحها ، فإن إنشاء تجمع Autorelease الخاص بك هو في الأساس أمر غير محدد.

لا يحتاج أي من الأمثلة الخاصة بك إلى تجمع Autorelease. تجمعات Autorelease لا تهتم إلا بالأشياء التي تم صدرها:

NSArray *foo = [NSArray array];
NSObject *bar = [[[NSObject alloc] init] autorelease];

تتم تهيئة السلسلة الأولى الخاصة بك باستخدام سلسلة حرفية وبالتالي ربما تكون خاصة فيما يتعلق بإدارة الذاكرة (ربما يعرف شخص آخر المزيد). تتسرب السلسلة الثانية الخاصة بك ، لا يحدث حوض السباحة فرقًا. يتم إصدار السلسلة الثالثة الخاصة بك بشكل صحيح ، مرة أخرى لا تحدث مجموعة الفرق.

هذا هو المكان الذي ستحتاج فيه إلى تجمع:

- (void) someMethodThatRunsOnAThread {
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
    NSString *foo = [@"foo" uppercaseString];
    [pool drain];
}

هنا foo ستتسرب السلسلة إذا لم يكن المسبح موجودًا. لاحظ أنني أتصل drain بدلاً من release على حمام السباحة-على iOS ، لا يوجد فرق ، ولكن في البيئات التي تم جمعها في القمامة يختلف الاثنان ، لذلك من الأفضل أن يكونوا عادةً ما يطلق على واحد صحيح.

لاحظ أيضًا أنك قد تحتاج إلى تجمع على الرغم من أنك لا تقم بإعداد أي كائنات بنفسك ، فقد يكون هناك العديد من عمليات الذاكرة التي يتم في مكان ما في الكود الذي تتصل به في طريقتك.

أعتقد أن هذا يجب أن يكون مثل هذا:

-(void) doSomething {

   NSAutorelease *pool = [[NSAutorelasepool alloc] init];


   NSString *myString = [[[NSString alloc] initWithString:@"Hello"] autorelease];

   // or create string like this (automatically autoreleased)
   NSString *myString = [NSString stringWithString:@"Hello"];

   [pool release];
}

يجب عليك إرسال رسالة Autorelease ، إلى كائنات داخل Autorelease Pool. سيتم إصدارها عند إرسال رسالة الإصدار إلى البلياردو.

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