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;
}
needed.do 로서 다른 인스턴스를 작성하는 경우는, 다음의 순서에 따릅니다.
+ (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;
}
사용방법:
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
는 블록을 1회만 디스패치함으로써 레이스 조건을 해결하는 데 도움이 됩니다.
Static
를 사용하면 호출 수에 관계없이 그 가치를 "기억"할 수 있습니다.어떻게 기억하죠?sharedInstance의 정확한 이름을 가진 새 인스턴스를 다시 생성할 수 없습니다. 원래 생성된 인스턴스와 함께 작동합니다.
호출 사용 안 함alloc
init
(즉, 우리는 아직alloc
init
메서드는 NSObject 서브클래스이기 때문에 sharedInstance 클래스에서는 사용하지 않는 것이 좋습니다만, 이것을 실현하려면 ,+(instancetype)sharedInstance
여러 스레드에서 동시에 여러 번 시도하더라도 한 번만 시작하도록 제한되며 값을 기억합니다.
코코아 자체와 함께 제공되는 가장 일반적인 시스템 중 일부는 다음과 같습니다.
[UIApplication sharedApplication]
[NSUserDefaults standardUserDefaults]
[NSFileManager defaultManager]
[NSBundle mainBundle]
[NSOperations mainQueue]
[NSNotificationCenter defaultCenter]
기본적으로 중앙 집중식 효과를 필요로 하는 모든 것은 일종의 싱글톤 디자인 패턴을 따라야 합니다.
또는 Objective-C는 NSObject 및 모든 서브클래스에 +(void) 초기화 방법을 제공합니다.항상 클래스의 메서드 앞에 호출됩니다.
iOS6에서 한번 브레이크 포인트를 설정하고 스택 프레임에 한번 dispatch_one이 표시되었습니다.
Singleton Class : 어떤 경우에도 여러 클래스의 개체를 만들 수 없습니다.
+ (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];
}
수용된 답변에는 두 가지 문제가 있으며, 이는 목적에 관련이 있을 수도 있고 그렇지 않을 수도 있습니다.
- init 메서드에서 sharedInstance 메서드가 다시 호출되면(예를 들어 싱글톤을 사용하는 다른 오브젝트가 거기에서 구축되기 때문에) 스택오버플로우가 발생합니다.
- 클래스 계층의 경우 계층 내 구체적인 클래스별로 싱글톤이 1개(sharedInstance 메서드가 호출된 계층의 첫 번째 클래스)가 아닌 싱글톤만 존재합니다.
다음 코드는 이 두 가지 문제를 모두 해결합니다.
+ (instancetype)sharedInstance {
static id mutex = nil;
static NSMutableDictionary *instances = nil;
//Initialize the mutex and instances dictionary in a thread safe manner
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
mutex = [NSObject new];
instances = [NSMutableDictionary new];
});
id instance = nil;
//Now synchronize on the mutex
//Note: do not synchronize on self, since self may differ depending on which class this method is called on
@synchronized(mutex) {
id <NSCopying> key = (id <NSCopying>)self;
instance = instances[key];
if (instance == nil) {
//Break allocation and initialization into two statements to prevent a stack overflow, if init somehow calls the sharedInstance method
id allocatedInstance = [self alloc];
//Store the instance into the dictionary, one per concrete class (class acts as key for the dictionary)
//Do this right after allocation to avoid the stackoverflow problem
if (allocatedInstance != nil) {
instances[key] = allocatedInstance;
}
instance = [allocatedInstance init];
//Following code may be overly cautious
if (instance != allocatedInstance) {
//Somehow the init method did not return the same instance as the alloc method
if (instance == nil) {
//If init returns nil: immediately remove the instance again
[instances removeObjectForKey:key];
} else {
//Else: put the instance in the dictionary instead of the allocatedInstance
instances[key] = instance;
}
}
}
}
return instance;
}
#import <Foundation/Foundation.h>
@interface SingleTon : NSObject
@property (nonatomic,strong) NSString *name;
+(SingleTon *) theSingleTon;
@end
#import "SingleTon.h"
@implementation SingleTon
+(SingleTon *) theSingleTon{
static SingleTon *theSingleTon = nil;
if (!theSingleTon) {
theSingleTon = [[super allocWithZone:nil] init
];
}
return theSingleTon;
}
+(id)allocWithZone:(struct _NSZone *)zone{
return [self theSingleTon];
}
-(id)init{
self = [super init];
if (self) {
// Set Variables
_name = @"Kiran";
}
return self;
}
@end
위의 코드가 도움이 되길 바랍니다.
싱글톤을 빨리 만들어야 한다면
class var sharedInstance: MyClass {
struct Singleton {
static let instance = MyClass()
}
return Singleton.instance
}
또는
struct Singleton {
static let sharedInstance = MyClass()
}
class var sharedInstance: MyClass {
return Singleton.sharedInstance
}
이 방법으로 사용할 수 있습니다.
let sharedClass = LibraryAPI.sharedInstance
언급URL : https://stackoverflow.com/questions/7568935/how-do-i-implement-an-objective-c-singleton-that-is-compatible-with-arc
'source' 카테고리의 다른 글
vba에서 VLOOKUP 함수 쓰기 (0) | 2023.04.24 |
---|---|
Bash 스크립트에서 중복 항목 제거 (0) | 2023.04.24 |
FormBuilder 컨트롤의 수동 값 설정 (0) | 2023.04.24 |
왼쪽 조인 포함 상위 1위 (0) | 2023.04.19 |
행 및 열 인덱스로 WPF 그리드의 제어에 프로그래밍 방식으로 액세스하는 방법은 무엇입니까? (0) | 2023.04.19 |