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

时间:2011-08-12 02:15:13

标签: objective-c singleton

如何确保用户不调用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;
    }
}

4 个答案:

答案 0 :(得分:6)

我见过它有两种方式。

  1. init内抛出异常。
  2. 让init返回的对象成为你的单例对象。
  3. 但是要明确,不要这样做。这是不必要的,会让你的单身人士难以测试和分类。

    编辑以添加示例

    在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;
    }
    

    让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;
    }
    

答案 1 :(得分:5)

使用UNAVAILABLE_ATTRIBUTE取消init方法,并实施initPrivate

+ (instancetype)shareInstance;

- (instancetype)init UNAVAILABLE_ATTRIBUTE;
+ (instancetype)new UNAVAILABLE_ATTRIBUTE;

实施

+ (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;
}

答案 2 :(得分:2)

简短的回答:你做不到; Objective-C没有私有方法的概念。

查看this similar question的答案。

答案 3 :(得分:0)

您无法在Objective-C中将方法设为私有。如果调用了错误的初始化程序,您可以引发NSException

- (id)init
{
     [NSException exceptionWithName:@"InvalidOperation" reason:@"Cannot invoke init." userInfo:nil];
}