2011-08-12 18 views
2

我如何確保用戶不要調用init,而是客戶端應該調用sharedSingleton來獲取共享實例。objc中的單例模式,如何保持init私有?

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

回答

0

您不能在Objective-C中使方法保密。如果調用了錯誤的初始化程序,則可以調出NSException

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

簡答:你不能; Objective-C沒有私有方法的概念。

檢查出this similar question的答案。

+2

它們可與一種擴展(又名「空類」),雖然效仿,但我認爲它不會隱藏繼承的初始化。 –

7

我已經看到它做了兩種方法。

  1. init內部拋出異常。
  2. 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; 
} 

有初始化回到你的單身

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

我相信這兩個答案都是錯誤的。如果init方法拋出異常,你將無法創建sharedSingleton是第一個地方。而且,返回單例對象會讓你處於無限循環,因爲單例會再次調用init。 –

+0

我編輯了答案以提供示例,因爲我確實瞭解了實現細節。 – kubi

2

使用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; 
}