在iPhone上意外的Singleton类行为,我做错了什么?

时间:2009-06-16 15:47:49

标签: iphone objective-c singleton

我正在实现一个单例类,如下所示:

static Singleton* _singletonInstance;

@implementation Singleton

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

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

初始化只在第一次有人调用实例时调用。然后我有一个方法,我可以调用它来设置一些实例变量。所以最终看起来像这样。

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

当我在对象中获得这个单例的实例时,它第一次正常工作;但是,在我dealloc并创建需要单例实例的对象的新副本后,当我尝试调用setup函数时,我得到一个BAD ACCESS错误。

只是为了测试我在进行设置调用之前打印出实例的地址,并且两次都报告相同的地址,但是当我检查错误日志中的BAD ACCESS调用时,它会列出一个完全不同的内存地址。

当我打印它时,有没有人知道为什么这个指向实例的指针看起来很好,但是当我调用它时,它似乎指向随机数据?

4 个答案:

答案 0 :(得分:3)

指针值看起来有效,因为它曾经是,但很可能是内存已被释放,这就是为什么它指向看起来像随机数据。

您已经使用上面的[[Singleton alloc] init]获得了一个引用,但是其他地方是否有release可能正在执行?我打赌你的代码正在调用instance,然后调用release - 稍后,即使你的代码从未获得引用。对于单身人士来说,这不应该是必要的。只是一个猜测...

答案 1 :(得分:1)

您是否在某处释放了_singletonInstance?

答案 2 :(得分:1)

我使用的是更复杂但非常稳定的Singleton模板版本(使用Brandon "Quazie" Kwaselow Blog中的描述):

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;
}

答案 3 :(得分:1)

Valerii的代码更适合实现单例,但几乎可以肯定的是,调用[Singleton实例]的代码运行就好像它拥有所有权而没有实际使用retain获取所有权,然后才释放它。

查找您的错误,并阅读Memory Managment Rules

此外,在Xcode中,enable NSZombieEnabled和控制台会在您尝试在对象发布后向其发送消息时显示。