实例化单例类

问题描述:

我创建了一个单例类来跟踪我的iPhone应用程序中的数据。我知道singleton只需要实例化一次,但是实例化它的最佳位置是什么?这应该在appDelegate中完成吗?我想能够从多个类中调用这个单例(包含一个NSMutableArray),以便我可以访问该数组。实例化单例类

这里是我的课我写道:

#import "WorkoutManager.h" 

static WorkoutManager *workoutManagerInstance; 

@implementation WorkoutManager 
@synthesize workouts; 

+(WorkoutManager*)sharedInstance { 
    if(!workoutManagerInstance) { 
     workoutManagerInstance = [[WorkoutManager alloc] init]; 
    } 
    return workoutManagerInstance; 
} 

-(id)init { 
    self = [super init]; 
    if (self) { 
     workouts = [[NSMutableArray alloc] init]; 
    } 
    return self; 
} 

@end 
+0

看看这个:http://*.com/questions/145154/what-does-your-objective-c-singleton-look-like – 2012-04-11 00:46:12

+0

或这样的:HTTP:// *.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc – 2012-04-11 00:47:03

+0

链接似乎是关于实施一个单身人士。我已经有了我的书面和运作。我在我的一个类中的一个IBAction中实例化它,但是我很困惑我是否应该在别处实例化它以便它是全局的? – TopChef 2012-04-11 00:49:17

几乎在所有情况下,单例的一点是你不关心谁首先实例化它。谁是第一个打电话给[Something sharedSomething]的人将是创作者。你想要使用“How do I implement an Objective-C singleton that is compatible with ARC?”中给出的模式,它将确保单例只创建一次。

这可能是最简单的方法:

static MyClass* theInstance = nil; 

+ (MyClass*) sharedInstance { 
    @synchronized(self) { 
     if (! theInstance) { 
      theInstance = [[MyClass alloc] init]; 
     } 
    } 

    return theInstance; 
} 

...所以在您要访问的单身地方,你只是做[MyClass sharedInstance]以便获得对该实例的参考。

请注意,这不会防止人们在您的单例类中手动调用allocinit来创建其他实例。如果您需要这样做,您可以以类似于上述的方式实施init,以防止使用allocinit创建/返回其他实例。然而,在实践中,单身人士课程最常使用sharedInstance方法(有时候在名称上有微小的变化,如[UIApplication sharedApplication])。

+1

我推荐在http://*.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc回答中给出的GCD模式。 @synchronize解决方案的价格要高一些,而且自从添加dispatch_once以来,没有理由支付这些费用。 – 2012-04-11 00:52:49

+0

两种方法都可以,是的。我个人更喜欢'@ synchronized';我只是觉得它更具可读性。 – aroth 2012-04-11 00:55:57

单身人士通常懒惰地实例化 - 第一次访问时,实例被创建并从访问方法返回。随后对访问方法的调用仅返回已创建的实例。

标准模式是:1.锁定或以其他方式使以下线程安全(即dispatch_once())。 2.检查单实例是否已经创建。 3.如果没有,创建它。 4.释放锁定(如果适用)。 5.返回实例。

如果您因某种原因需要创建实例,则可能会出现这种情况。当类被添加到运行时时,运行时会发送类方法+load,该运行时在应用程序执行的早期阶段。 (+initialize看起来也是一个候选人 - 它在运行时正好在类接收到它的第一个(其他)消息之前发送(不包括+load) - 但它实际上并没有给你任何东西,因为它会被发送紧接在您发送sharedInstance之前。)

gcc __constructor__function attribute也可以工作(在clang中也是如此),尽管被记录为未针对ObjC实施。具有此属性的函数将在输入main()之前调用。不过,我不太确定这个选项的内存管理含义。运行时应该全部设置好,但是不会有autorelease池。

+0

这里非常有用的技巧。 '+ load'是一个非常有用的工具,可以知道(尽管你经常不需要它)。 – 2012-04-11 00:54:12

通常单类实例化被访问的第一次:

static SomeClass *_instance = nil; 

+ (SomeClass *) instance { 
    @synchronized(self) { 
     if (!_instance) 
      _instance = [[self alloc] init]; 
    } 
    return _instance; 
} 

我使用此代码实例单身。GCD需要同步的护理

+ (SingletonClass *)sharedInstance { 
    static SingletonClass *sharedInstance; 
    static dispatch_once_t onceToken; 
    dispatch_once(&onceToken, ^{ 
    sharedInstance = [[SingletonClass alloc] init]; 
    sharedInstance.property = [Property new]; 
    }); 
    return sharedInstance; 
}