假设我在我的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;
}
再一次,你怎么看?
答案 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
}
我覆盖release
和dealloc
以确保不会释放单例。如果您不这样做,您应该使用sharedInstance
方法保留并自动释放它。如果要支持多线程,还应同步访问theInstance
变量。