我创建了一个单例类来跟踪我的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 :(得分:6)
在几乎所有情况下,单身人士的观点是你不关心谁首先实例化它。无论谁是第一个致电[Something sharedSomething]
的人都将成为创造者。您想要使用“How do I implement an Objective-C singleton that is compatible with ARC?”中给出的模式。它将确保仅创建一次单例。
答案 1 :(得分:2)
单身人士通常懒惰地实例化 - 第一次访问它们时,实例将从访问方法创建并返回。对访问方法的后续调用只返回已创建的实例。
标准模式是:1。锁定或以其他方式使线程安全(即dispatch_once()
)。 2.检查是否已创建单个实例。 3.如果没有,请创建它。 4.释放锁定(如果适用)。 5.返回实例。
如果由于某种原因需要,可以提前创建实例。当类被添加到运行时时,运行时将发送类方法+load
,这是应用程序执行的早期阶段。 (+initialize
似乎也是候选者 - 它是在课程收到第一个(其他)消息(也不包括+load
)之前由运行时发送的 - 但它实际上并没有让你任何事情,因为它会在您发送sharedInstance
之前立即发送。)
gcc __constructor__
function attribute也有效(尽管也是如此),尽管记录为没有为ObjC实施。在输入main()
之前,将调用具有此属性的函数。不过,我不太清楚这个选项对内存管理的影响。应该全部设置运行时,但是还没有自动释放池。
答案 2 :(得分:1)
这可能是最简单的方法:
static MyClass* theInstance = nil;
+ (MyClass*) sharedInstance {
@synchronized(self) {
if (! theInstance) {
theInstance = [[MyClass alloc] init];
}
}
return theInstance;
}
...所以在你想要访问单例的地方,你只需要[MyClass sharedInstance]
来获得对实例的引用。
请注意,这不会阻止人们在您的单例类上手动调用alloc
和init
来创建其他实例。如果您需要这样做,您可以采用与上述类似的方式实施init
,以防止使用alloc
和init
创建/返回其他实例。
然而,在实践中,单身类最常使用sharedInstance
方法(有时在命名方面有微小变化,例如[UIApplication sharedApplication]
)。
答案 3 :(得分:0)
通常在第一次访问单例类时实例化它们:
static SomeClass *_instance = nil;
+ (SomeClass *) instance {
@synchronized(self) {
if (!_instance)
_instance = [[self alloc] init];
}
return _instance;
}
答案 4 :(得分:0)
我正在使用此代码来实例化单例。 GCD负责同步
+ (SingletonClass *)sharedInstance {
static SingletonClass *sharedInstance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
sharedInstance = [[SingletonClass alloc] init];
sharedInstance.property = [Property new];
});
return sharedInstance;
}