在Objective-C中使用init方法创建单例的安全方法

Ond*_*rej 11 objective-c nsobject ios

我想采用GCD方法将共享实例用于下一步,因此我创建了以下代码:

@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
Run Code Online (Sandbox Code Playgroud)

我假设该sharedInstance方法似乎没问题,但我不确定init方法.创建这个的原因是我不希望人们使用我的SDK,使用init方法,如果他们这样做...使它成为防弹.

Leo*_*Leo 12

我没有透明地将调用重定向到init单例实现,这可能会给SDK的用户造成非常混乱的行为,我建议不要允许调用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;
}
Run Code Online (Sandbox Code Playgroud)


Jus*_*dow 7

我想建议解决您问题的新方法。

NS_UNAVAILABLE您可以像这样在头文件中使用:

//Header file
@interface MyClass : NSObject
+ (instancetype)sharedInstance
- (instancetype)init NS_UNAVAILABLE;
//...
@end
Run Code Online (Sandbox Code Playgroud)

在这种情况下,init函数将无法从外部使用,也不会建议自动完成,并且您将能够正常使用init实现文件中的方法。

当您创建一个单例类时,我建议您new通过将此行添加到头文件中来使方法也不可用:

+ (instancetype)new NS_UNAVAILABLE;
Run Code Online (Sandbox Code Playgroud)

还有一种使方法不可用的旧方法(也可以在标头中使用):

- (instancetype) init __attribute__((unavailable("Use 'sharedInstance' instead of 'init' as this class is singleton.")));
Run Code Online (Sandbox Code Playgroud)

如果您想提示一些有关不可用的消息,可以使用此功能。