这个有效的代码是否可以创建一个NIB实例化的单例?

时间:2011-03-27 23:55:29

标签: objective-c cocoa

假设我在我的NIB中实例化了MyGreatClass类的对象(通常只需将“Object”拖到NIB并将其类设置为MyGreatClass)。

我希望在我的代码库中的任何地方访问该实例,而不引入耦合,即不会像疯了一样传递对象,并且没有插入它,比如说[NSApp delegate]。 (后者会使AppDelegate随着时间的推移变得非常笨重。)

我问:以下是否是一个很好的代码来实现这个目标?

//imports

static MyGreatClass *theInstance = nil;

@implementation MyGreatClass

+ (MyGreatClass *)sharedInstance
{
  NSAssert(theInstance != nil, @"instance should have been loaded from NIB");
  return theInstance;
}

- (id)init //waking up from NIB will call this
{
  if (!theInstance)
    theInstance = self;
  return theInstance;
}

// ...

如果按预期工作,我会在加载应用程序后通过sharedInstance访问我的实例。

您怎么看?

更新:嗯,在第二个想法,上面的init方法可能是矫枉过正。这更容易思考:

- (id)init
{
  NSAssert(!theInstance, @"instance shouldn't exist yet because only "
                         @"the NIB-awaking process should call this method");
  theInstance = self;
  return theInstance;
}

再一次,你怎么看?

1 个答案:

答案 0 :(得分:1)

创建单例的正确方法是覆盖allocWithZone:以确保无法创建另一个对象。覆盖init允许创建新对象,但不能初始化。它被丢弃,因为init方法只是忽略它并返回已经创建的对象。我将如何做到这一点:

+ (MyGreatClass *)sharedInstance {
    NSAssert(theInstance != nil, @"instance should have been created from NIB");
    return theInstance;
}

+ (MyGreatClass *)allocWithZone:(NSZone *)zone {
    if(theInstance) return theInstance;
    return [[self alloc] init];
}

- (id)init {
    if(theInstance) return theInstance;
    if(self = [super init]) {
        theInstance = self;
        // other initialization
    }
    return self;
}

- (void)release {}
- (void)dealloc {
    return;
    [super dealloc]; // Prevent compiler from issuing warning for not calling super
}

我覆盖releasedealloc以确保不会释放单例。如果您不这样做,您应该使用sharedInstance方法保留并自动释放它。如果要支持多线程,还应同步访问theInstance变量。