2010-03-09 4 views
1

싱글 톤 인스턴스를 만들 때 일부 메서드를 재정의하는 코드 스 니펫 (CocoaFundamentals 가이드에 있음)으로 약간 혼란 스럽습니다.애플 싱글턴 예제 쿼리?

static id sharedReactor = nil; 

+(id)sharedInstance { 
    if(sharedReactor == nil) sharedReactor = [[super allocWithZone:NULL] init]; 
    return sharedReactor; 
} 

. 싱글 인스턴스가 + sharedInstance 방법을 생성 된 코드에서

+(id)allocWithZone:(NSZone *)zone { 
    return[[self sharedInstance] retain]; 
} 

-(id)retain { 
    return self; 
} 

는 [슈퍼 allocWithZone을 : NILL] 호출하는 슈퍼 클래스에서 (내 경우 NSObject의 인) 당신이 그것을 사용하려고하면 allocWithZone 위에만 호출됩니다 새 싱글 톤을 만들 수 있습니다.

혼란 스러울 정도의 비트는 보유를 사용하는 것입니다. 특히 보유를 보는 것 또한 자기를 되돌리기 위해 무시됩니다. 사람이 설명 할 수, 그것은 쓸 수 없습니다 :

+(id)allocWithZone:(NSZone *)zone { 
    return [self sharedInstance]; 
} 

-(id)retain { 
    return self; 
} 

EDIT_001 : I (아래 참조) 나는이 다음에 가기로 결정했다 웹에 대한 의견 독서 다양한 게시물을 바탕으로

필요한 경우 두 번째 또는 세 번째 인스턴스를 만들 수있는 옵션이있는 공유 싱글 톤 접근 방식을 선택했습니다. 또한이 단계에서는 간단한 iPhone 앱의 MVC 모델 부분에 싱글 톤 만 사용하므로 스레드 안전을 유지하기로했습니다. 나는 그것의 중요성을 잘 알고 있으며, 아이폰 프로그래밍에 익숙해 져서 (아마도 두 번 호출 될 수있는 서브 클래스 문제를 염두에 두면서) 초기화 대신에 + 초기화를 사용할 것이다. 또한 dealloc을 추가했다. 싱글 톤 (singleton)이 더 이상 필요하지 않으면 제대로 정리해야합니다.

@interface SharedManager : NSObject 
+(id)sharedInstance; 
@end 

@implementation SharedManager 

static id myInstance = nil; 

+(id)sharedInstance { 
    if(myInstance == nil) { 
     myInstance = [[self alloc] init]; 
    } 
    return myInstance; 
} 

-(void)dealloc { 
    NSLog(@"_deal: %@", [self class]); 
    [super dealloc]; 
    myInstance = nil; 
} 
@end 

테스트에서 I는 I가 할당 해제에 세트를 정적 변수 전무했다 또는 원래의 객체에 대한 포인터를 유지하였습니다. 처음에는 인스턴스의 정적 범위를 기대하고 있었기 때문에 약간 혼란 스러웠습니다. 대신 클래스를 추측 해 봅시다.

환호 게리

답변

5

먼저이 코드를 사용하지 마십시오. 간단한 싱글 톤을 위해이 모든 것을 할 이유는 거의 없습니다. Apple은 "강제 싱글 톤"을 시연 중입니다. 두 가지를 만들 수 없다는 점에서입니다. 정말 필요하지는 않습니다. 싱글 톤 생성자를 가진 대부분의 Cocoa 객체가 사용하는 "공유 싱글 톤"접근법을 거의 항상 사용할 수 있습니다. 그것 뿐이다

+ (MYManager *)sharedManager 
{ 
    static MYManager *sharedManager = nil; 
    if (sharedManager == nil) 
    { 
     sharedManager = [[self alloc] init]; 
    } 
    return sharedManager; 
} 

:

여기에 공유 싱글 톤을 구현하는 나의 선호하는 방법입니다. 다른 코드는 필요하지 않습니다. +sharedManager을 사용하는 발신자는 공유 인스턴스를 가져옵니다. +alloc을 호출 한 발신자는 실제로 원할 경우 고유 한 인스턴스를 만들 수 있습니다. 이것은 NSNotificationCenter과 같은 유명한 "싱글 톤"이 작동하는 방식입니다. 자신의 사적인 알림 센터를 정말로 원한다면, 수업에서 금지해야하는 이유는 없습니다. 이 접근 방식에는 다음과 같은 이점이 있습니다.

  • 코드가 적습니다.
  • 비공유 인스턴스가 유용한 경우보다 유연합니다.
  • 가장 중요한 점은 코드가 말하는대로 작동합니다. 그가 +alloc으로 고유 한 인스턴스를 만들고 있다고 생각하는 호출자는 객체의 내부 구현 세부 사항을 알 필요가있는 놀랄만 한 "어색한 동작을 멀리"하는 동작을 경험하지 않습니다.

공유 할 수 없습니다 고유 자원에 대한 질문 맵의 오브젝트 (그리고 이러한 상황이 발생할 정말 드문 일이), 당신은 여전히 ​​+alloc 속임수를 사용하지 말아야하기 때문에 당신은 정말 는 강제 싱글을이 필요한 경우 그것을 시행 할 수 있습니다. 이것은 새로운 인스턴스를 만들려고하는 프로그래밍 오류를 가린다. 대신 프로그래밍 오류를 다음과 같이 catch해야합니다.

+ (MYManager *)sharedManager 
{ 
    static MYManager *sharedManager = nil; 
    if (sharedManager == nil) 
    { 
     sharedManager = [[self alloc] initSharedManager]; 
    } 
    return sharedManager; 
} 

- (id)init 
{ 
    NSAssert(NO, @"Attempting to instantiate new instance. Use +sharedManager."); 
    return nil; 
} 

// Private method. Obviously don't put this in your .h 
- (id)initSharedManager 
{ 
    self = [super init]; 
    .... 
    return self; 
} 
+1

스레드 안전성을 논의하기 위해이를 업데이트 할 수 있습니다. 마이크 애쉬 (Mike Ash)는 다른 싱글 톤 문제와 관련하여 좋은 소식을 가지고 있습니다. http://www.mikeash.com/pyblog/friday-qa-2009-10-02-care-and-feeding-of-singletons.html – nall

+0

더 나은 : 독자들은 Mike Ash의 게시물을 확인해야합니다. 이것은 thread-safety를 위해 이것을 확장하는 방법에 대해 매우 철저합니다. 공유 싱글 톤에 대한 스레드 안전성 문제는 초기 생성에만 영향을 미칩니다. 내가 쓰레딩을 일반적으로 처리하는 방법 때문에이 종류의 스레드 문제가 발생하는 것은 매우 드물다 (내 코드에서 싱글 톤의 첫 번째 사용이 작업자 스레드에있을 가능성은 매우 낮다). 즉, 구현하기에 너무 싸기 때문에 Mike가 초기화를 사용하는 유혹을 받는다. 그리고 나는 "너무 초기 init"문제가 대부분의 상황에서는 일어나지 않을 것이라고 생각한다. –

+1

@Rob 여전히 여러 인스턴스를 허용하지 않습니다. 그것은 대회에서 그들을 "허용하지 않는다". Peter Hosey는 싱글 톤을보다 적절하게 구현하는 방법에 대한 훌륭한 글을 올렸습니다. http://boredzo.org/blog/archives/2009-06-17/doing-it-wrong –