[objective-c] ARC와 호환되는 Objective-C 싱글 톤을 어떻게 구현합니까?

Xcode 4.2에서 자동 참조 카운팅 (ARC)을 사용할 때 올바르게 컴파일되고 동작하는 싱글 톤 클래스를 어떻게 변환 (또는 작성)합니까?



답변

당신이 이미하고있는 것과 똑같은 방식으로 :

+ (instancetype)sharedInstance
{
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
        // Do any other initialisation stuff here
    });
    return sharedInstance;
}


답변

필요에 따라 다른 인스턴스를 작성하려면 다음을 수행하십시오.

+ (MyClass *)sharedInstance
{
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[MyClass alloc] init];
        // Do any other initialisation stuff here
    });
    return sharedInstance;
}

그렇지 않으면 다음을 수행해야합니다.

+ (id)allocWithZone:(NSZone *)zone
{
    static MyClass *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [super allocWithZone:zone];
    });
    return sharedInstance;
}


답변

ARC 및 비 ARC 용 버전입니다.

사용하는 방법:

MySingletonClass.h

@interface MySingletonClass : NSObject

+(MySingletonClass *)sharedInstance;

@end

MySingletonClass.m

#import "MySingletonClass.h"
#import "SynthesizeSingleton.h"
@implementation MySingletonClass
SYNTHESIZE_SINGLETON_FOR_CLASS(MySingletonClass)
@end


답변

이것은 ARC에서 제 패턴입니다. GCD를 사용하여 새로운 패턴을 만족시키고 Apple의 오래된 인스턴스화 방지 패턴도 만족시킵니다.

@implementation AAA
+ (id)alloc
{
    return  [self allocWithZone:nil];
}
+ (id)allocWithZone:(NSZone *)zone
{
    [self doesNotRecognizeSelector:_cmd];
    abort();
}
+ (instancetype)theController
{
    static AAA* c1  =   nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^
    {
        c1  =   [[super allocWithZone:nil] init];

        // For confirm...       
        NSLog(@"%@", NSStringFromClass([c1 class]));    //  Prints AAA
        NSLog(@"%@", @([c1 class] == self));            //  Prints 1

        Class   real_superclass_obj =   class_getSuperclass(self);
        NSLog(@"%@", @(real_superclass_obj == self));   //  Prints 0
    });

    return  c1;
}
@end


답변

이 답변을 읽고 다른 답변을 읽으십시오.

솔루션을 이해하지 못하는 것보다 싱글 톤의 의미와 요구 사항이 무엇인지 이해해야합니다.

싱글 톤을 성공적으로 만들려면 다음 3을 수행 할 수 있어야합니다.

  • 경쟁 조건 이있는 경우 여러 SharedInstance 인스턴스를 동시에 만들 수 없어야합니다!
  • 여러 번의 호출 중 가치를 기억하고 유지하십시오.
  • 한 번만 작성하십시오. 진입 점을 제어합니다.

dispatch_once_t블록을 한 번만 전달 하여 경쟁 조건 을 해결하는 데 도움이됩니다 .

Static여러 번의 호출에서 값을 “기억”하는 데 도움이됩니다. 어떻게 기억합니까? 정확한 이름의 sharedInstance를 가진 새 인스턴스를 다시 만들 수는 없으며 원래 만들어진 인스턴스와 만 작동합니다.

sharedInstance 클래스에서 호출을 사용하지 않고alloc init (즉 alloc init, NSObject 서브 클래스이므로 메소드를 사용하지 않아야 함) +(instancetype)sharedInstance, 다른 스레드의 다중 시도에 관계없이 한 번만 시작 하도록 제한 되는을 사용하여이를 달성 합니다. 동시에 그 가치를 기억하십시오.

코코아 자체와 함께 제공되는 가장 일반적인 시스템 싱글 톤은 다음과 같습니다.

  • [UIApplication sharedApplication]
  • [NSUserDefaults standardUserDefaults]
  • [NSFileManager defaultManager]
  • [NSBundle mainBundle]
  • [NSOperations mainQueue]
  • [NSNotificationCenter defaultCenter]

기본적으로 중앙 집중식 효과가 필요한 것은 일종의 싱글 톤 디자인 패턴을 따라야합니다.


답변

또는 Objective-C는 NSObject 및 모든 하위 클래스에 + (void) initialize 메소드를 제공합니다. 항상 클래스의 메소드보다 먼저 호출됩니다.

iOS 6에서 중단 점을 한 번에 설정했으며 dispatch_once가 스택 프레임에 나타났습니다.


답변

싱글 톤 클래스 : 어떤 경우에도 또는 어떤 방식으로도 둘 이상의 클래스 객체를 만들 수 없습니다.

+ (instancetype)sharedInstance
{
    static ClassName *sharedInstance = nil;
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        sharedInstance = [[ClassName alloc] init];
        // Perform other initialisation...
    });
    return sharedInstance;
}
//    You need need to override init method as well, because developer can call [[MyClass alloc]init] method also. that time also we have to return sharedInstance only. 

-(MyClass)init
{
   return [ClassName sharedInstance];
}