Wenn Sie auf iOS 4.0 oder höher abzielen können
Ist es mit GCD der beste Weg, Singleton in Objective-C (thread-sicher) zu erstellen?
+ (instancetype)sharedInstance
{
static dispatch_once_t once;
static id sharedInstance;
dispatch_once(&once, ^{
sharedInstance = [[self alloc] init];
});
return sharedInstance;
}
instancetype
. Die Code-Vervollständigung ist viel besser, wenn Sie diese anstelle von verwendenid
.Antworten:
Dies ist eine absolut akzeptable und threadsichere Methode, um eine Instanz Ihrer Klasse zu erstellen. Es kann technisch gesehen kein "Singleton" sein (da es immer nur eines dieser Objekte geben kann), aber solange Sie nur die
[Foo sharedFoo]
Methode verwenden, um auf das Objekt zuzugreifen, ist dies gut genug.quelle
Instanztyp
instancetype
ist nur eine der vielen SpracherweiterungenObjective-C
, mit jeder neuen Version werden weitere hinzugefügt.Wisse es, liebe es.
Nehmen Sie als Beispiel, wie Sie durch die Beachtung der Details auf niedriger Ebene Einblicke in leistungsstarke neue Möglichkeiten zur Transformation von Objective-C erhalten.
Siehe hier: Instanztyp
quelle
MySingleton.h
MySingleton.m
quelle
init
?MySingleton
zum Beispiel inMySingleton.m
Ich rufe an[super alloc]
Sie können vermeiden, dass die Klasse zugewiesen wird, indem Sie die Zuweisungsmethode überschreiben.
quelle
Dave hat recht, das ist vollkommen in Ordnung. In den Apple-Dokumenten zum Erstellen eines Singletons finden Sie Tipps zur Implementierung einiger anderer Methoden, um sicherzustellen, dass nur eine erstellt werden kann, wenn Klassen die sharedFoo-Methode NICHT verwenden.
quelle
Wenn Sie sicherstellen möchten, dass [[MyClass alloc] init] dasselbe Objekt wie sharedInstance zurückgibt (meiner Meinung nach nicht erforderlich, aber einige Leute möchten es), können Sie dies sehr einfach und sicher mit einem zweiten dispatch_once tun:
Dadurch kann jede Kombination von [[MyClass alloc] init] und [MyClass sharedInstance] dasselbe Objekt zurückgeben. [MyClass sharedInstance] wäre nur ein bisschen effizienter. So funktioniert es: [MyClass sharedInstance] ruft [[MyClass alloc] init] einmal auf. Andere Codes könnten es auch beliebig oft aufrufen. Der erste Aufrufer von init führt die "normale" Initialisierung durch und speichert das Singleton-Objekt in der init-Methode. Bei späteren Aufrufen von init wird die zurückgegebene Zuordnung vollständig ignoriert und dieselbe sharedInstance zurückgegeben. Das Ergebnis der Zuweisung wird freigegeben.
Die + sharedInstance-Methode funktioniert wie immer. Wenn es nicht der erste Aufrufer ist, der [[MyClass alloc] init] aufruft, ist das Ergebnis von init nicht das Ergebnis des Alloc-Aufrufs, aber das ist in Ordnung.
quelle
Sie fragen, ob dies der "beste Weg ist, um Singleton zu erstellen".
Ein paar Gedanken:
Erstens, ja, dies ist eine thread-sichere Lösung. Dieses
dispatch_once
Muster ist die moderne, thread-sichere Methode zum Generieren von Singletons in Objective-C. Keine Sorge da.Sie haben jedoch gefragt, ob dies der "beste" Weg ist, dies zu tun. Man sollte jedoch anerkennen, dass das
instancetype
und[[self alloc] init]
in Verbindung mit Singletons möglicherweise irreführend ist.Der Vorteil von
instancetype
ist, dass es eine eindeutige Methode ist, zu erklären, dass die Klasse in Unterklassen unterteilt werden kann, ohne auf eine Art von Klasse zurückzugreifenid
, wie wir es früher getan haben.Aber das
static
in dieser Methode stellt Unterklassenherausforderungen. Was wäre, wennImageCache
undBlobCache
Singletons beide Unterklassen einerCache
Oberklasse wären, ohne ihre eigenesharedCache
Methode zu implementieren ?Damit dies funktioniert, müssen Sie sicherstellen, dass Unterklassen ihre eigenen implementieren
sharedInstance
Methode (oder wie auch immer Sie sie für Ihre bestimmte Klasse nennen) .Unterm Strich
sharedInstance
sieht Ihr Original so aus, als würde es Unterklassen unterstützen, aber nicht. Wenn Sie Unterklassen unterstützen möchten, fügen Sie zumindest eine Dokumentation hinzu, die zukünftige Entwickler warnt, dass sie diese Methode überschreiben müssen.Für eine optimale Interoperabilität mit Swift möchten Sie dies wahrscheinlich als eine Eigenschaft definieren, nicht als eine Klassenmethode, z. B.:
Dann können Sie einen Getter für diese Eigenschaft schreiben (die Implementierung würde das von
dispatch_once
Ihnen vorgeschlagene Muster verwenden):Dies hat den Vorteil, dass ein Swift-Benutzer, wenn er es verwendet, Folgendes tun würde:
Beachten Sie, dass dies nicht der Fall ist
()
, da wir es als Eigenschaft implementiert haben. Ab Swift 3 wird im Allgemeinen auf Singletons zugegriffen. Die Definition als Eigenschaft erleichtert die Interoperabilität.Abgesehen davon, wenn Sie sich ansehen, wie Apple ihre Singletons definiert, ist dies das Muster, das sie übernommen haben, z. B. ist ihr
NSURLSession
Singleton wie folgt definiert:Eine weitere, sehr geringfügige Überlegung zur Swift-Interoperabilität war der Name des Singletons. Es ist am besten, wenn Sie den Namen des Typs einfügen und nicht
sharedInstance
. Wenn die Klasse beispielsweise warFoo
, können Sie die Singleton-Eigenschaft als definierensharedFoo
. Oder wenn die Klasse warDatabaseManager
, können Sie die Eigenschaft aufrufensharedManager
. Dann könnten Swift-Benutzer Folgendes tun:Wenn Sie wirklich verwenden möchten
sharedInstance
, können Sie den Swift-Namen jederzeit deklarieren , wenn Sie möchten:Wenn Sie Objective-C-Code schreiben, sollten wir nicht zulassen, dass die Swift-Interoperabilität andere Entwurfsüberlegungen überwiegt. Wenn wir jedoch Code schreiben können, der beide Sprachen ordnungsgemäß unterstützt, ist dies vorzuziehen.
Ich stimme anderen zu, die darauf hinweisen, dass, wenn Sie möchten, dass dies ein echter Singleton ist, bei dem Entwickler ihre eigenen Instanzen nicht (versehentlich) instanziieren können / sollten, das
unavailable
Qualifikationsmerkmal aktiviert istinit
undnew
umsichtig ist.quelle
So erstellen Sie einen thread-sicheren Singleton:
und dieser Blog erklärt Singleton sehr gut Singletons in Objc / Kakao
quelle
quelle
quelle