답변:
당신이 이미하고있는 것과 똑같은 방식으로 :
+ (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;
}
static
메소드 / 함수 내에 선언 된 @David 변수는 메소드 / 함수 static
외부에 선언 된 변수 와 동일하며 해당 메소드 / 함수의 범위 내에서만 유효합니다. +sharedInstance
메소드를 통한 모든 개별 실행 (다른 스레드에서도)은 동일한 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;
}
dispatch_once()
비트는 첫 번째 예에서도 추가 인스턴스를 얻지 못한다는 것을 의미합니다.
[[MyClass alloc] init]
우회하고 무시할 수 있으므로 False sharedInstance
입니다. DongXu, Peter Hosey의 Singleton 기사를 보아야 합니다. 재정의 위하여려고하는 경우에 allocWithZone:
생성되는 이상의 인스턴스를 방지하기 위해, 당신은 또한 오버라이드 (override) 할 필요가 init
다시 초기화되는 것을 공유 인스턴스를 방지 할 수 있습니다.
allocWithZone:
버전입니다. 고마워.
사용하는 방법:
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
c1
의 인스턴스가 되지 AAA
않습니까? 당신은 호출 할 필요 +alloc
에 self
하지에 super
.
super
는 수퍼 클래스 객체를 의미하지 않습니다. 수퍼 클래스 객체를 얻을 수 없습니다. 메시지를 수퍼 클래스 버전의 메서드로 라우팅하는 것입니다. super
여전히 포인트 self
클래스. 수퍼 클래스 객체를 얻으려면 런타임 리플렉션 함수를 가져와야합니다.
-allocWithZone:
메소드는 오버라이드 포인트를 제공하기위한 런타임 할당 함수에 대한 간단한 체인입니다. 따라서 궁극적으로 self
pointer == 현재 클래스 객체가 할당 자에게 전달되고 마지막으로 AAA
인스턴스가 할당됩니다.
super
클래스 메소드에서 작동 하는 방식 의 미묘함을 잊어 버렸습니다 .
이 답변을 읽고 다른 답변을 읽으십시오.
솔루션을 이해하지 못하는 것보다 싱글 톤의 의미와 요구 사항이 무엇인지 이해해야합니다.
싱글 톤을 성공적으로 만들려면 다음 3을 수행 할 수 있어야합니다.
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]
기본적으로 중앙 집중식 효과가 필요한 것은 일종의 싱글 톤 디자인 패턴을 따라야합니다.
싱글 톤 클래스 : 어떤 경우에도 또는 어떤 방식으로도 둘 이상의 클래스 객체를 만들 수 없습니다.
+ (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];
}
허용되는 답변에는 두 가지 문제가 있으며, 귀하의 목적과 관련이있을 수도 있고 그렇지 않을 수도 있습니다.
다음 코드는이 두 문제를 모두 처리합니다.
+ (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