代码之家  ›  专栏  ›  技术社区  ›  Skyler

iPhone上意外的单例类行为,我做错什么了吗?

  •  1
  • Skyler  · 技术社区  · 15 年前

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

    static Singleton* _singletonInstance;
    
    @implementation Singleton
    
    +(void)initialize
    { 
        _singletonInstance = [[Singleton alloc] init]; 
    }
    
    +(Singleton*)instance
    {
        return(_singletonInstance);
    }
    

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

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

    当我在一个对象中获得这个singleton的实例时,它第一次工作得很好;但是,当我释放并创建一个需要singleton实例的对象的新副本后,当我试图调用安装函数时,会得到一个错误的访问错误。

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

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

    4 回复  |  直到 15 年前
        1
  •  3
  •   Jared Oberhaus    15 年前

    指针值看起来是有效的,因为它以前是有效的,但很可能内存是空闲的,这就是为什么它所指向的看起来像随机数据的原因。

    你已经用你的 [[Singleton alloc] init] 上面,但是有没有 release 可能在其他地方执行?我敢打赌你的密码在呼叫 instance 然后 释放 -稍后,即使您的代码从未获得引用。不管怎么说,这对单身汉来说是不必要的。只是猜测…

        2
  •  1
  •   Eric Petroelje    15 年前

    你是否在某个地方解除单身身份?

        3
  •  1
  •   Valerii Hiora    15 年前

    我正在使用更加复杂,但非常稳定的单例模板版本(从 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;
    }
    
        4
  •  1
  •   Peter N Lewis    15 年前

    Valerii的代码更好地实现了单例,但问题几乎可以肯定的是,调用[singleton实例]的代码的操作方式就像它拥有所有权而实际上没有使用retain获得所有权一样,然后发布它。

    找到你的错误,然后阅读 Memory Managment Rules .

    此外,在XCODE中, enable NSZombieEnabled 当您试图在对象被释放后发送消息时,控制台会显示给您。