Bunun "singleton oluşturmanın en iyi yolu" olup olmadığını soruyorsunuz.
İlk olarak, evet, bu iş parçacığı için güvenli bir çözümdür. Bu dispatch_once
model Objective-C'de tek ton üretmenin modern, iş parçacığı açısından güvenli bir yoludur. Endişeye gerek yok.
Yine de, bunu yapmanın "en iyi" yolu olup olmadığını sordunuz. Ancak şunu kabul etmeliyiz ki instancetype
ve[[self alloc] init]
birlikte, tekillerle birlikte kullanıldığında potansiyel olarak yanıltıcı .
Bunun yararı instancetype
, sınıfın, id
dün yaptığımız gibi bir tür başvurmadan alt sınıflara ayrılabileceğini açıklamanın açık bir yoludur .
Ancak static
bu yöntemde alt sınıflandırma zorlukları ortaya çıkar. Ya ImageCache
ve BlobCache
singletonların her ikisi de Cache
kendi sharedCache
yöntemlerini uygulamadan bir üst sınıftan alt sınıflarsa ?
ImageCache *imageCache = [ImageCache sharedCache]; // fine
BlobCache *blobCache = [BlobCache sharedCache]; // error; this will return the aforementioned ImageCache!!!
Bunun işe yaraması için, alt sınıfların kendi sharedInstance
(veya kendi sınıfınız için ne derseniz söyleyin) yöntemini uyguladığından emin olmanız gerekir.
Alt satırda, orijinaliniz alt sınıfları destekleyecek gibi sharedInstance
görünüyor , ancak olmayacak. Alt sınıflamayı desteklemek istiyorsanız, en azından gelecekteki geliştiricileri bu yöntemi geçersiz kılmaları konusunda uyaran belgeleri ekleyin.
Swift ile en iyi birlikte çalışabilirlik için, muhtemelen bunu bir sınıf yöntemi değil, bir özellik olarak tanımlamak istersiniz, örneğin:
@interface Foo : NSObject
@property (class, readonly, strong) Foo *sharedFoo;
@end
Sonra devam edip bu özellik için bir alıcı yazabilirsiniz (uygulama dispatch_once
önerdiğiniz kalıbı kullanır ):
+ (Foo *)sharedFoo { ... }
Bunun yararı, bir Swift kullanıcısı kullanmaya başlarsa, şöyle bir şey yapmalarıdır:
let foo = Foo.shared
Not, hayır ()
, çünkü onu bir özellik olarak uyguladık. Swift 3'ten başlayarak, genellikle tektonlara bu şekilde erişilir. Dolayısıyla onu bir özellik olarak tanımlamak, birlikte çalışabilirliği kolaylaştırmaya yardımcı olur.
Bir kenara, Apple'ın kendi tektonlarını nasıl tanımladığına bakarsanız, bu benimsedikleri kalıptır, örneğin NSURLSession
tekilleri aşağıdaki gibi tanımlanır:
@property (class, readonly, strong) NSURLSession *sharedSession;
Swift ile birlikte çalışabilirlik konusundaki bir diğer önemli husus, singleton'un adıydı. Bunun yerine türün adını dahil edebiliyorsanız en iyisidir sharedInstance
. Örneğin, sınıf buysa Foo
, singleton özelliğini olarak tanımlayabilirsiniz sharedFoo
. Veya sınıf olsaydı DatabaseManager
, özelliği çağırabilirsiniz sharedManager
. Ardından Swift kullanıcıları şunları yapabilir:
let foo = Foo.shared
let manager = DatabaseManager.shared
Açıkçası, gerçekten kullanmak istiyorsanız sharedInstance
, istediğiniz zaman Swift adını her zaman bildirebilirsiniz:
@property (class, readonly, strong) Foo* sharedInstance NS_SWIFT_NAME(shared);
Açıkça, Objective-C kodu yazarken, Swift birlikte çalışabilirliğinin diğer tasarım hususlarından daha ağır basmasına izin vermemeliyiz, ancak yine de, her iki dili de zarif bir şekilde destekleyen bir kod yazabilirsek, bu tercih edilir.
Bunun, geliştiricilerin kendi örneklerini (yanlışlıkla) somutlaştıramayacağı / kazaramayacağı gerçek bir singleton olmasını istiyorsanız, unavailable
niteleyicinin init
ve new
ihtiyatlı olduğuna dikkat çeken diğerlerine katılıyorum .