我的单例访问方法通常是一些变种:
static MyClass *gInstance = NULL;
+ (MyClass *)instance
{
@synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
我能做些什么来改善这一点呢?
我的单例访问方法通常是一些变种:
static MyClass *gInstance = NULL;
+ (MyClass *)instance
{
@synchronized(self)
{
if (gInstance == NULL)
gInstance = [[self alloc] init];
}
return(gInstance);
}
我能做些什么来改善这一点呢?
当前回答
根据我下面的另一个回答,我认为你应该这样做:
+ (id)sharedFoo
{
static dispatch_once_t once;
static MyFoo *sharedFoo;
dispatch_once(&once, ^ { sharedFoo = [[self alloc] init]; });
return sharedFoo;
}
其他回答
你不想在self上同步…因为self对象还不存在!最终锁定一个临时id值。你想要确保没有其他人可以运行类方法(sharedInstance, alloc, allocWithZone:等),所以你需要在类对象上同步:
@implementation MYSingleton
static MYSingleton * sharedInstance = nil;
+( id )sharedInstance {
@synchronized( [ MYSingleton class ] ) {
if( sharedInstance == nil )
sharedInstance = [ [ MYSingleton alloc ] init ];
}
return sharedInstance;
}
+( id )allocWithZone:( NSZone * )zone {
@synchronized( [ MYSingleton class ] ) {
if( sharedInstance == nil )
sharedInstance = [ super allocWithZone:zone ];
}
return sharedInstance;
}
-( id )init {
@synchronized( [ MYSingleton class ] ) {
self = [ super init ];
if( self != nil ) {
// Insert initialization code here
}
return self;
}
}
@end
关于单例宏代码的详细解释在Cocoa With Love博客上
http://cocoawithlove.com/2008/11/singletons-appdelegates-and-top-level.html。
这是我放在一起的一个宏:
http://github.com/cjhanson/Objective-C-Optimized-Singleton
它基于马特·加拉格尔的作品 但是将实现改为使用谷歌的Dave MacLachlan所描述的方法swizzling。
我欢迎评论/贡献。
KLSingleton是: 可子类化(到n阶) 弧相容 使用alloc和init是安全的 装载 线程安全的 无锁(使用+initialize,而不是@synchronize) Macro-free Swizzle-free 简单的
克林格尔顿
我只是想把这个放在这里,这样我就不会弄丢了。这个的优点是它可以在InterfaceBuilder中使用,这是一个巨大的优势。这是我问的另一个问题:
static Server *instance;
+ (Server *)instance { return instance; }
+ (id)hiddenAlloc
{
return [super alloc];
}
+ (id)alloc
{
return [[self instance] retain];
}
+ (void)initialize
{
static BOOL initialized = NO;
if(!initialized)
{
initialized = YES;
instance = [[Server hiddenAlloc] init];
}
}
- (id) init
{
if (instance)
return self;
self = [super init];
if (self != nil) {
// whatever
}
return self;
}