programing

GCD의 dispatch_once in Objective-C를 사용하여 싱글톤을 생성합니다.

javamemo 2023. 4. 25. 21:46
반응형

GCD의 dispatch_once in Objective-C를 사용하여 싱글톤을 생성합니다.

iOS 4.0 이상을 대상으로 할 수 있습니다.

GCD를 사용하여 Objective-C(스레드 세이프)에서 싱글톤을 생성하는 가장 좋은 방법입니까?

+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;
    dispatch_once(&once, ^{
        sharedInstance = [[self alloc] init];
    });
    return sharedInstance;
}

이것은 클래스의 인스턴스를 만들기에 완벽하게 적합하고 안전한 방법입니다. 말하면 '싱글톤은 아닐 수 있지만, '싱글톤'은 '싱글톤'이 아니라 '싱글톤'만 쓰면 됩니다.[Foo sharedFoo]이겁니다.

설치 유형입니다.

instancetype에 대한 많은 언어 확장 중 하나일 뿐입니다.Objective-C새로운 릴리스마다 더 많은 항목이 추가됩니다.

알아요, 좋아요.

또한 낮은 수준의 세부 사항에 주의를 기울이면 Objective-C를 혁신할 수 있는 강력하고 새로운 방법에 대한 통찰력을 얻을 수 있음을 보여주는 사례로 활용하십시오.

instancetype을 참조하십시오.


+ (instancetype)sharedInstance
{
    static dispatch_once_t once;
    static id sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}

+ (Class*)sharedInstance
{
    static dispatch_once_t once;
    static Class *sharedInstance;

    dispatch_once(&once, ^
    {
        sharedInstance = [self new];
    });    
    return sharedInstance;
}

MySingleton.h.

@interface MySingleton : NSObject

+(instancetype)sharedInstance;

+(instancetype)alloc __attribute__((unavailable("alloc not available, call sharedInstance instead")));
-(instancetype)init __attribute__((unavailable("init not available, call sharedInstance instead")));
+(instancetype)new __attribute__((unavailable("new not available, call sharedInstance instead")));
-(instancetype)copy __attribute__((unavailable("copy not available, call sharedInstance instead")));

@end

마이싱글톤입니다.

@implementation MySingleton

+(instancetype)sharedInstance {
    static dispatch_once_t pred;
    static id shared = nil;
    dispatch_once(&pred, ^{
        shared = [[super alloc] initUniqueInstance];
    });
    return shared;
}

-(instancetype)initUniqueInstance {
    return [super init];
}

@end

할당 메서드를 덮어쓰면 클래스가 할당되지 않도록 할 수 있습니다.

@implementation MyClass

static BOOL useinside = NO;
static id _sharedObject = nil;


+(id) alloc {
    if (!useinside) {
        @throw [NSException exceptionWithName:@"Singleton Vialotaion" reason:@"You are violating the singleton class usage. Please call +sharedInstance method" userInfo:nil];
    }
    else {
        return [super alloc];
    }
}

+(id)sharedInstance
{
    static dispatch_once_t p = 0;
    dispatch_once(&p, ^{
        useinside = YES;
        _sharedObject = [[MyClass alloc] init];
        useinside = NO;
    });   
    // returns the same object each time
    return _sharedObject;
}

데이브 말이 맞아요, 아주 좋아요.클래스에서 sharedFoo 메서드를 사용하지 않도록 선택한 경우, 다른 메서드를 구현하는 방법에 대한 팁은 싱글톤 작성에 대한 Apple 문서를 참조하십시오.

[MyClass allocate] init이 sharedInstance와 동일한 개체를 반환하도록 하려면(내 생각에는 필요하지 않지만 일부 사람들은 이를 원하지만) 두 번째 디스패치를 사용하여 매우 쉽고 안전하게 수행할 수 있습니다.

- (instancetype)init
{
    static dispatch_once_t once;
    static Class *sharedInstance;

    dispatch_once(&once, ^
    {
        // Your normal init code goes here. 
        sharedInstance = self;
    });

    return sharedInstance;
}

이렇게 하면 [MyClass allocate] init과 [MyClass sharedInstance]의 조합이 동일한 개체를 반환할 수 있습니다. [MyClass sharedInstance]가 조금 더 효율적입니다.작동 방식: [MyClass sharedInstance]에서 [MyClass allocate] init을 한 번 호출합니다.다른 코드도 여러 번 호출할 수 있습니다.첫 번째 초기화 호출자는 "정상" 초기화를 수행하고 init 메서드에 싱글톤 개체를 저장합니다.나중에 init을 호출하면 반환된 할당이 완전히 무시되고 동일한 sharedInstance가 반환됩니다. 할당 결과는 할당 해제됩니다.

+sharedInstance 메서드는 항상 그랬던 것처럼 작동합니다.[MyClass allocate] init을 호출한 첫 번째 호출자가 아니라면, init의 결과는 할당 호출의 결과가 아니지만 괜찮습니다.

이것이 "싱글톤을 만드는 최선의 방법"인지 묻습니다.

몇 가지 생각이 있습니다.

  1. 첫째, 네, 이것은 스레드 세이프 솔루션입니다.이건 ㅇㅇㅇㅇㅇㅇ.dispatch_once패턴은 Objective-C에서 싱글톤을 생성하는 현대적인 스레드 세이프 방법입니다.네, 그렇습니다.

  2. 하지만 이것이 "최선의" 방법인지 물어보셨습니다.하지만이 말은 인정해야 합니다.instancetype그리고요.[[self alloc] init]싱글톤과 함께 사용하면 오해의 소지가 있습니다.

    의 이점입니다.instancetype수업의 종류에 구애받지 않고 세분화할 수 있다는 을 명확히 선언하는 입니다.id작년처럼요

    하지만 ㅇㅇㅇㅇㅇ는요.static이 방법에서는 하위 분류 과제를 제시합니다.면 어쩌지ImageCache그리고요.BlobCache싱글톤은 둘 다 아류였습니다.Cache슈퍼클래스입니다.sharedCache법?? ???

    ImageCache *imageCache = [ImageCache sharedCache];  // fine
    BlobCache *blobCache = [BlobCache sharedCache];     // error; this will return the aforementioned ImageCache!!!
    

    이렇게 위해서는 하위 계층이 자신의 하위 계층을 구현해야 합니다.sharedInstance(또는 특정 클래스에 대해 무엇이라 부르든) 방법을 사용합니다.

    요컨대, 당신의 원본입니다.sharedInstance 서브클래스를 지원하는 것처럼 보이지만, 지원하지 않습니다.하위 분류를 지원하려면 적어도 향후 개발자에게 이 방법을 재정의해야 함을 경고하는 문서를 포함해야 합니다.

  3. Swift와의 최상의 상호 운용성을 위해 다음과 같이 클래스 메서드가 아닌 속성으로 정의할 수 있습니다.

    @interface Foo : NSObject
    @property (class, readonly, strong) Foo *sharedFoo;
    @end
    

    그런 다음 이 속성에 대해를 쓰면 됩니다(구현에서는 getter를 사용합니다).dispatch_once안제제하신패패패패다다.

    + (Foo *)sharedFoo { ... }
    

    이 방법의 이점은 Swift 사용자가 이 제품을 사용할 경우 다음과 같은 작업을 수행할 수 있다는 것입니다.

    let foo = Foo.shared
    

    참고: 없습니다.()자산으로 구현했기 때문입니다.Swift 3부터는 일반적으로 싱글톤에 액세스하는 방법입니다.따라서 이를 속성으로 정의하면 상호 운용성을 촉진하는 데 도움이 됩니다.

    덧붙여서, Apple이 싱글톤을 어떻게 살펴보면, 이것이 그들이 채택한 패턴입니다. 예를 들어, 애플은 ,, apple apple e붙 、 이이 、 이이 、 이이 、 이이 이이 、 이이이 이이이 。 예를 들어, 그들의 싱글톤과 같은 패턴입니다.NSURLSession이겁니다.

    @property (class, readonly, strong) NSURLSession *sharedSession;
    
  4. Swift 상호 운용성에 대한 또 다른 아주 사소한 고려 사항은 싱글톤의 이름입니다.유형 이름을 포함하는 것이 좋습니다.sharedInstance예를 들어 수업이 ㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴㄴFoo, 싱글톤 성질을 , ㄴㄴㄴ데 하다, 라고 정의할 수 있습니다sharedFoo아니면 수업을 듣거나요.DatabaseManager, 재산이라고 부르셔도 됩니다sharedManager그러면 Swift 사용자는 다음을 수행할 수 있습니다.

    let foo = Foo.shared
    let manager = DatabaseManager.shared
    

    확실히 꼭 쓰려면 쓰세요, 쓰세요, 쓰세요.sharedInstance, 언제든지 Swift 이름을 선언할 수 있습니다. 즉, Swift 이름을 선언할 수 있습니다

    @property (class, readonly, strong) Foo* sharedInstance NS_SWIFT_NAME(shared);
    

    Objective-C 코드를 작성할 때 Swift 상호 운용성을 다른 설계 고려 사항보다 우선시해서는 안 되지만, 그래도 두 언어를 모두 원활하게 지원하는 코드를 작성할 수 있다면 더 좋습니다.

  5. 개발자가 자신의 인스턴스를 인스턴스화할 수 없는 한 싱글톤이 바란다면, 다른 사람들은 합니다.unavailable한정자 입니다.init그리고요.new네, 그렇습니다.

스레드 세이프 싱글턴을 작성하려면 다음과 같이 하십시오.

@interface SomeManager : NSObject
+ (id)sharedManager;
@end

/* thread safe */
@implementation SomeManager

static id sharedManager = nil;

+ (void)initialize {
    if (self == [SomeManager class]) {
        sharedManager = [[self alloc] init];
    }
}

+ (id)sharedManager {
    return sharedManager;
}
@end

그리고 이 블로그는 싱글톤을 objc/singletons로 매우 잘 설명합니다.

@interface className : NSObject{
+(className*)SingleTonShare;
}

@implementation className

+(className*)SingleTonShare{

static className* sharedObj = nil;
static dispatch_once_t once = 0;
dispatch_once(&once, ^{

if (sharedObj == nil){
    sharedObj = [[className alloc] init];
}
  });
     return sharedObj;
}
//Create Singleton  
  +( instancetype )defaultDBManager
    {

        static dispatch_once_t onceToken = 0;
        __strong static id _sharedObject = nil;

        dispatch_once(&onceToken, ^{
            _sharedObject = [[self alloc] init];
        });

        return _sharedObject;
    }


//In it method
-(instancetype)init
{
    self = [super init];
  if(self)
     {
   //Do your custom initialization
     }
     return self;
}

언급URL : https://stackoverflow.com/questions/5720029/create-singleton-using-gcds-dispatch-once-in-objective-c 입니다.

반응형