回答:
あなたがすでに(すべき)行ってきたのとまったく同じ方法で:
+ (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]
およびバイパスできるためsharedInstance
。DongXu、Peter Hoseyのシングルトンの記事をご覧ください。上書きallocWithZone:
してインスタンスが作成さ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
ポインタ==現在のクラスオブジェクトがアロケータに渡され、最後にAAA
インスタンスが割り当てられます。
super
はクラスメソッドでどのように機能するかの微妙なことを忘れていました。
この答えを読んでから、他の答えを読んでください。
シングルトンが何を意味するのか、そしてそれを理解していない場合、ソリューションを理解できないよりも、その要件が何であるかを最初に知る必要があります。
シングルトンを正常に作成するには、以下を実行できる必要があります3。
dispatch_once_t
ブロックを1回だけディスパッチできるようにすることで、競合状態を解決するのに役立ちます。
Static
任意の数の呼び出しにわたってその値を「記憶」するのに役立ちます。どのように覚えていますか?共有インスタンスの正確な名前を持つ新しいインスタンスを再度作成することはできません。最初に作成されたインスタンスでのみ機能します。
使用していない呼び出しalloc
init
(つまり、我々はまだ持っているalloc
init
私たちはNSObjectのサブクラスをしているので、我々はそれらを使用してはならないものの、メソッド)を、当社のsharedInstanceクラスに、私たちが使用してこれを実現する+(instancetype)sharedInstance
唯一のことに制限されており、一度開始した別のスレッドからの複数の試みに関係なく、同時に、その価値を思い出してください。
Cocoa自体に付属する最も一般的なシステムシングルトンには、次のものがあります。
[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];
}
承認された回答には2つの問題があり、目的に関連する場合とそうでない場合があります。
次のコードは、これらの問題の両方を処理します。
+ (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