开发者

Is this valid code to create a NIB-instantiated singleton?

开发者 https://www.devze.com 2023-02-19 22:53 出处:网络
Assume that I instantiate an object of class MyGreatClass in my NIB (as usual by simply dragging an \"Object\" to the NIB and settings its class to MyGreatClass).

Assume that I instantiate an object of class MyGreatClass in my NIB (as usual by simply dragging an "Object" to the NIB and settings its class to MyGreatClass).

I want access to that instance anywhere in my codebase, without introducing coupling, i.e. without passing objects around like crazy, and without having an outlet to it in, say, [NSApp delegate]. (The latter would make AppDelegate terribly bulky with time.)

I ask: Is the following considered a good code to accomplish this?

//imports

static MyGreatClass *theInstance = nil;

@implementation MyGreatClass

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

- (id)i开发者_开发技巧nit //waking up from NIB will call this
{
  if (!theInstance)
    theInstance = self;
  return theInstance;
}

// ...

If this work as expected, I would after the app is loaded be able to access my instance via sharedInstance.

What do you think?

UPDATE: Hmm, on the second thought, the above init method maybe overkill. This is way simpler to think about:

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

Again, what do you think?


The proper way to create a singleton is to override allocWithZone: to ensure another object cannot be created. Overriding init allows the new object to be created, but not initialized. It is thrown away because the init method simply ignores it and returns the object that has been created already. Here is how I would do it:

+ (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
}

I overrode release and dealloc to ensure that the singleton would not be deallocated. If you don't do this, you should retain and autorelease it in the sharedInstance method. If you want to support multithreading, you should also synchronize access to the theInstance variable.

0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号