سؤال

ما هو الفرق بين ما يلي 2 طرق لتخصيص و تهيئة كائن ؟

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

و

self.aController= [[AController alloc] init];

معظم أبل سبيل المثال استخدام الأسلوب الأول.لماذا تخصيص init وجوه ثم الإفراج فورا ؟

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

المحلول

كل كائن لديه مرجع.عندما يذهب إلى 0 ، والهدف من ذلك هو deallocated.

على افتراض الملكية كما أعلن @property (retain):

أول سبيل المثال ، سطرا:

  1. يتم إنشاء الكائن من قبل alloc, ، فقد إشارة العد من 1.
  2. الكائن سلم self's setAController: الطريقة التي يرسل عليها retain رسالة (لأن الأسلوب لا أعرف من أين كائن قادم من) ، تزايد عدد مرجعها إلى 2.
  3. رمز الدعوة لم تعد بحاجة إلى هدف في حد ذاته, لذلك المكالمات release, decrementing مرجع إلى 1.

الثاني المثال في الأساس لا الخطوات 1 و 2 ولكن ليس 3 ، لذلك في النهاية كائن مرجع هو 2.

القاعدة هي أنه إذا قمت بإنشاء كائن ، أنت مسؤول عن إطلاقه عند الانتهاء من ذلك معها.في المثال الخاص بك ، رمز فعلت مع tempAController بعد ذلك بتعيين الخاصية.هو واضع طريقة مسؤولية الدعوة retain إذا كان يحتاج هذا الكائن حول عصا.

من المهم أن نتذكر أن self.property = foo; في الهدف-C هو في الحقيقة مجرد اختصار [self setProperty:foo]; وأن setProperty: الطريقة سيكون الإبقاء على أو نسخ الكائنات حسب الحاجة.

إذا كان العقار أعلن @property (copy), ثم الكائن قد تم نسخها بدلا من الاحتفاظ بها.في المثال الأول ، الكائن الأصلي سيطلق سراحهم على الفور ؛ في المثال الثاني ، الأصلي كائن مرجع سيكون 1 على الرغم من أنه ينبغي أن يكون 0.إذا كنت لا تزال ترغب في كتابة التعليمات البرمجية الخاصة بك بنفس الطريقة.

إذا كان العقار أعلن @property (assign), ثم self لا يدعي ملكية الكائن, و شخص آخر يحتاج إلى الاحتفاظ بها.في هذه الحالة, المثال الأول أن تكون غير صحيحة.هذه الأنواع من خصائص نادرة ، عادة ما تستخدم فقط على وجوه المندوبين.

نصائح أخرى

كما ذكر آخرون ، وهما مقتطفات الشفرة تظهر لك هي لا يعادلها (على إدارة الذاكرة الأسباب).السبب الأول هو المختار على هذا الأخير:

صياغة صحيحة من شأنه أن

self.aController= [[[AController alloc] init] autorelease];

مقارنة مع السابق ، وهذا يضيف مقدار حمل إضافي من خلال استخدام autorelease بركة, و في بعض الحالات يؤدي إلى حياة الكائن دون داع الموسعة (حتى autorelease تجمع صدر) والتي سوف تزيد من التطبيق الخاص بك الذاكرة.

أخرى "ممكن" تنفيذ (اعتمادا على سبيل المثال هو من) هو ببساطة:

aController = [[AController alloc] init];

إلا أن تحديد متغير مثيل مباشرة بقوة في أي مكان آخر من في الحرف الأول أو dealloc الأسلوب.في أماكن أخرى يجب عليك دائما استخدام أسلوب استرجاع القيمة الأساليب.

هذا يقودنا ثم إلى التنفيذ هو موضح في نموذج التعليمات البرمجية:

AController *tempAController = [[AController alloc] init];
self.aController = tempAController;
[tempAController release];

هذا يلي أفضل الممارسات منذ:

  • فإنه يتجنب autorelease;
  • يجعل إدارة الذاكرة دلالات على الفور واضحة ؛
  • فإنه يستخدم أسلوب استرجاع قيمة الأسلوب لتعيين سبيل المثال متغير.

ملحوظة أيضا أن لديك الرغبة في قطع رمز وصولا الى خط واحد هو السبب في كثير من الناس استخدام Autorelease:

self.aController = [[[AController alloc] init] autorelease];

وعلى الرغم من الناحية النظرية على autorelease فون هو بطريقة ما أكثر تكلفة (لم يسمع تفسيرا واضحا لماذا)، وبالتالي قد ترغب في اطلاق سراح صراحة الحق بعد تعيين الكائن في مكان آخر.

إذا كنت تستخدم كسكودي، يمكن أن تساعدك على اكتشاف هذا الرمز مع محلل ثابت. مجرد ضرب البناء >> بناء وتحليل

وهذا سوف تظهر لك رسالة مفيدة جدا في مثل هذه القطع من التعليمات البرمجية.

وشيء آخر هو أن نلاحظ أن المثال الخاص بك يعتمد على تعريفproperty من aController أيضا.

إذا تم تعريفها بأنها @property (readwrite, retain) id aController; ثم يعمل سبيل المثال، في حين إذا تم تعريف أنها @property (readwrite, assign) id aController; ثم الدعوة اضافية للافراج عن سيسبب الكائن يمكن deallocated.

هل يمكن أن تفعل أيضا

@property (nonatomic, retain)AController *aController;
...
self.aController= [[AController alloc] init];
[aController release];

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

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