在Objective-C中用init方法创build单例的安全方法
我想采用共享实例下一步的GCD方法,所以我创build了以下代码:
@implementation MyClass static id sharedInstance; #pragma mark Initialization + (instancetype)sharedInstance { static dispatch_once_t once; dispatch_once(&once, ^{ sharedInstance = [[self alloc] init]; }); return sharedInstance; } - (instancetype)init { if (sharedInstance) { return sharedInstance; } @synchronized(self) { self = [super init]; if (self) { sharedInstance = self; } return self; } } @end
我假设sharedInstance
方法似乎没问题,但我不确定有关的init方法。 创build这个的原因是,我不希望人们使用我的SDK,使用init方法,如果他们这样做…使其防弹。
而不是透明地将调用redirect到单向实现,这会给您的SDK用户造成非常混乱的行为,我build议不要根本调用init:
+ (instancetype)sharedInstance { static dispatch_once_t once; dispatch_once(&once, ^{ sharedInstance = [[self alloc] initPrivate]; }); return sharedInstance; } - (instancetype)init { @throw [NSException exceptionWithName:NSInternalInconsistencyException reason:@"..." userInfo:nil]; } - (instancetype)initPrivate { if (self = [super init]) { ... } return self; }
我想提出解决你的问题的新方法。
你可以像这样在头文件中使用NS_UNAVAILABLE
:
//Header file @interface MyClass : NSObject + (instancetype)sharedInstance - (instancetype)init NS_UNAVAILABLE; //... @end
在这种情况下, init
函数将无法从外部获得,不会被build议自动完成,并且您将能够正常使用执行文件中的init
方法。
当你正在做一个单身人士的课程时,我build议你把new
方法join到头文件中去:
+ (instancetype)new NS_UNAVAILABLE;
还有一个老方法使得方法不可用(也可以在头文件中使用):
- (instancetype) init __attribute__((unavailable("Use 'sharedInstance' instead of 'init' as this class is singleton.")));
如果你想提示一些关于不可用的消息,可以使用这个。
一般的观点是,试图保护你的单身免受这种错误是毫无意义的。 无论谁调用[[LUIMain alloc] init]
并创build一个单例,都会得到他们应得的。
而且你写的代码不是线程安全的。 如果我呼叫[[LUIMain alloc] init]
而其他人调用sharedInstance ,则sharedInstance将返回与下一次呼叫不同的对象。 (在init方法中@synchronized (self)
是没有意义的,因为第二个调用者会有不同的self)。