غير متوقع سلوك الطبقة سينغلتون على اي فون، أفعل شيئا خاطئا؟

StackOverflow https://stackoverflow.com/questions/1002364

  •  05-07-2019
  •  | 
  •  

سؤال

وأنا تنفيذ فئة المفرد كما يلي:

static Singleton* _singletonInstance;

@implementation Singleton

+(void)initialize
{ 
    _singletonInstance = [[Singleton alloc] init]; 
}

+(Singleton*)instance
{
    return(_singletonInstance);
}

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

_singleton = [Singleton instance];
[_singleton setupWithParams: blah];

عند أحصل على سبيل المثال من هذه المفردة داخل كائن، فإنه يعمل بشكل جيد للمرة الأولى. ومع ذلك، بعد أن dealloc وإنشاء نسخة جديدة من الكائن الذي يحتاج إلى مثيل المفرد، وأحصل على خطأ ACCESS BAD عندما أحاول استدعاء الدالة الإعداد.

وفقط لاختبار الأشياء I طباعة عنوان المثال قبل أن إجراء المكالمة الإعداد وفي كل مرة أنها تقريرا نفس العنوان، ولكن عندما تحقق سجل خطأ لدعوة ACCESS سيئة، وهو يسرد عنوان ذاكرة مختلفة تماما.

هل لديها أي أفكار لماذا يبدو هذا المؤشر إلى مثيل لتبدو جيدة عندما كنت طباعته، ولكن عندما أقوم بإجراء مكالمة إلى ذلك، فإنه على ما يبدو لافتا إلى بيانات عشوائية؟

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

المحلول

وقيمة المؤشر تبدو صالحة لأنها اعتادت أن تكون، ولكن على الأرجح تم free'd الذاكرة، وهذا هو السبب ما يشير إلى يشبه بيانات عشوائية.

ولقد اكتسبت إشارة واحدة مع [[Singleton alloc] init] الخاص بك أعلاه، ولكن هناك release مكان آخر التي يمكن تنفيذها؟ أراهن التعليمات البرمجية تدعو instance، ثم release جي في وقت لاحق، على الرغم من التعليمات البرمجية أبدا حصلت على إشارة. وينبغي أن لا يكون من الضروري لعن المفردة على أي حال. مجرد تخمين ...

نصائح أخرى

هل deallocing _singletonInstance الخاص بك في مكان ما؟

وأنا باستخدام أكثر تعقيدا بكثير، ولكن إصدار مستقر جدا من قالب سينغلتون (مأخوذة مع وصف من <لأ href = "http://blog.quazie.net/2009/04/sharedinstance-objective-cs-singleton- نموذج / "يختلط =" نوفولو noreferrer "> براندون" Quazie "Kwaselow مدونة ):

static SampleSingleton *sharedSampleSingletonDelegate = nil;

+ (SampleSingleton *)sharedInstance {
   @synchronized(self) {
      if (sharedSampleSingletonDelegate == nil) {
         [[self alloc] init]; // assignment not done here
      }
   }
   return sharedSampleSingletonDelegate;
}

+ (id)allocWithZone:(NSZone *)zone {
   @synchronized(self) {
      if (sharedSampleSingletonDelegate == nil) {
         sharedSampleSingletonDelegate = [super allocWithZone:zone];
         // assignment and return on first allocation
         return sharedSampleSingletonDelegate;
      }
   }
   // on subsequent allocation attempts return nil
   return nil;
 }

- (id)copyWithZone:(NSZone *)zone
{
   return self;
}

- (id)retain {
   return self;
}

- (unsigned)retainCount {
   return UINT_MAX;  // denotes an object that cannot be released
}

- (void)release {
   //do nothing
}

- (id)autorelease {
   return self;
}

وكود فاليري هو أفضل لتنفيذ المفرد، ولكن المشكلة يكاد يكون من المؤكد أن التعليمات البرمجية الذي يستدعي [المثال سينغلتون] يعمل كما لو أنها ملكية من دون أخذ الواقع ملكية باستخدام الاحتفاظ بها، ومن ثم يتم بعد الافراج عن ذلك.

وانظر هناك لعلة الخاص بك، وقراءة إدارة الذاكرة قواعد .

وأيضا، في كسكودي، تمكين NSZombieEnabled وسوف تظهر لك وحدة التحكم عند محاولة رسالة الكائن بعد تم الافراج لها.

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