objc中的单例模式,如何保持init私有?

Jud*_*you 3 singleton objective-c

如何确保用户不调用init,而客户端应该调用sharedSingleton来获取共享实例.

@synthesize delegate;

- (id)init
{
    self = [super init];
    if (self) {
        // Initialization code here.
    }

    return self;
}

+ (LoginController *)sharedSingleton
{
    static LoginController *sharedSingleton;

    @synchronized(self)
    {
        if (!sharedSingleton)
            sharedSingleton = [[LoginController alloc] init];
        CdtMiscRegisterConnectionChangeListenerObjc(test_ConnectionChangeListenerCallback);
        return sharedSingleton;
    }
}
Run Code Online (Sandbox Code Playgroud)

kub*_*ubi 6

我已经看到它有两种方式.

  1. 在里面抛出一个例外init.
  2. 让init返回的对象成为你的单例对象.

但是要清楚,不要这样做.这是不必要的,会让你的单身人士难以测试和分类.

编辑以添加示例

在init中抛出异常

- (instancetype)init {
    [self doesNotRecognizeSelector:_cmd];
    return nil;
}

- (instancetype)initPrivate {
    self = [super init];
    if (self) {
    }
    return self;
}

+ (instancetype)sharedInstance {
    static MySingleton *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] initPrivate];
    });
    return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)

让init返回你的单身人士

- (instancetype)init {
    return [[self class] sharedInstance];
}

- (instancetype)initPrivate {
    self = [super init];
    if (self) {
    }
    return self;
}

+ (instancetype)sharedInstance {
    static MySingleton2 *sharedInstance;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[self alloc] initPrivate];
    });
    return sharedInstance;
}
Run Code Online (Sandbox Code Playgroud)


maq*_*ene 6

使用UNAVAILABLE_ATTRIBUTE废除init方法,并实现initPrivate

+ (instancetype)shareInstance;

- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;
Run Code Online (Sandbox Code Playgroud)

实行

+ (instancetype)shareInstance {
    static MyClass *shareInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        shareInstance = [[super allocWithZone:NULL] initPrivate];
    });
    return shareInstance;
}

- (instancetype)initPrivate {
    self = [super init];
    if (self) {

    }
    return self;
}

//  MARK: Rewrite
+ (id)allocWithZone:(struct _NSZone *)zone {
    return [MyClass shareInstance];
}

- (id)copyWithZone:(NSZone *)zone
{
    return self;
}
Run Code Online (Sandbox Code Playgroud)