सबसे पहले, हाँ, यह एक धागा-सुरक्षित समाधान है। यह dispatch_once
पैटर्न ऑब्जेक्टिव-सी में सिंगललेट जनरेट करने का आधुनिक, थ्रेड-सुरक्षित तरीका है। वहां कोई चिंता नहीं।
आपने पूछा, हालांकि, क्या यह करने का "सबसे अच्छा" तरीका है। एक को स्वीकार करना चाहिए, हालांकि, कि instancetype
और[[self alloc] init]
सिंग्लेट्स के साथ संयोजन में उपयोग किए जाने पर भ्रामक है।
इसका लाभ instancetype
यह है कि यह घोषित करने का एक नायाब तरीका है कि एक प्रकार का सहारा लिए बिना वर्ग को उपवर्गित किया जा सकता है।id
, जैसे कि हमें याचना में करना था।
लेकिन static
इस पद्धति में उपवर्ग चुनौतियों को प्रस्तुत करता है। क्या होगा अगर ImageCache
और BlobCache
सिंगलटन दोनों एक Cache
सुपरक्लास से अपने स्वयं के sharedCache
तरीके को लागू किए बिना उपवर्ग थे ?
ImageCache *imageCache = [ImageCache sharedCache]; // fine
BlobCache *blobCache = [BlobCache sharedCache]; // error; this will return the aforementioned ImageCache!!!
इस काम के लिए, आपको यह सुनिश्चित करना होगा कि उपवर्ग अपने स्वयं के sharedInstance
(या जो भी आप इसे अपने विशेष वर्ग के लिए कहते हैं) विधि को लागू करें।
निचला रेखा, आपका मूल sharedInstance
ऐसा दिखता है कि यह उपवर्गों का समर्थन करेगा, लेकिन यह नहीं होगा। यदि आप उपवर्ग का समर्थन करने का इरादा रखते हैं, तो बहुत कम से कम ऐसे दस्तावेज़ शामिल करें जो भविष्य के डेवलपर्स को चेतावनी देते हैं कि उन्हें इस पद्धति को ओवरराइड करना चाहिए।
स्विफ्ट के साथ सर्वश्रेष्ठ अंतर के लिए, आप शायद इसे एक संपत्ति के रूप में परिभाषित करना चाहते हैं, न कि एक वर्ग विधि, जैसे:
@interface Foo : NSObject
@property (class, readonly, strong) Foo *sharedFoo;
@end
फिर आप आगे जा सकते हैं और इस संपत्ति के लिए एक लिखने वाला लिख सकते हैं (कार्यान्वयन dispatch_once
आपके द्वारा सुझाए गए पैटर्न का उपयोग करेगा ):
+ (Foo *)sharedFoo { ... }
इसका लाभ यह है कि यदि कोई स्विफ्ट उपयोगकर्ता इसका उपयोग करने जाता है, तो वे कुछ ऐसा करेंगे:
let foo = Foo.shared
ध्यान दें, कोई भी नहीं है ()
, क्योंकि हमने इसे एक संपत्ति के रूप में लागू किया है। स्विफ्ट 3 को शुरू करते हुए, यह इस तरह से एकल रूप से एक्सेस किया जाता है। तो एक संपत्ति के रूप में इसे परिभाषित करने से उस अंतर को सुविधाजनक बनाने में मदद मिलती है।
एक तरफ के रूप में, यदि आप यह देखते हैं कि Apple अपने सिंगलेट्स को कैसे परिभाषित कर रहा है, तो यह पैटर्न है जिसे उन्होंने अपनाया है, उदाहरण के लिए उनके NSURLSession
सिंगलटन को इस प्रकार परिभाषित किया गया है:
@property (class, readonly, strong) NSURLSession *sharedSession;
एक और, बहुत मामूली स्विफ्ट इंटरऑपरेबिलिटी विचार सिंगलटन का नाम था। यह सबसे अच्छा है यदि आप टाइप के नाम को शामिल कर सकते हैं, बजाय sharedInstance
। उदाहरण के लिए, यदि वर्ग था Foo
, तो आप एकल संपत्ति को परिभाषित कर सकते हैं sharedFoo
। या यदि वर्ग था DatabaseManager
, तो आप संपत्ति को कॉल कर सकते हैं sharedManager
। तब स्विफ्ट उपयोगकर्ता कर सकते हैं:
let foo = Foo.shared
let manager = DatabaseManager.shared
स्पष्ट रूप से, यदि आप वास्तव में उपयोग करना चाहते हैं sharedInstance
, तो आप हमेशा स्विफ्ट नाम की घोषणा कर सकते हैं जो आपको चाहिए:
@property (class, readonly, strong) Foo* sharedInstance NS_SWIFT_NAME(shared);
स्पष्ट रूप से, जब उद्देश्य-सी कोड लिखते हैं, तो हमें स्विफ्ट इंटरऑपरेबिलिटी को अन्य डिज़ाइन के विचारों से आगे नहीं बढ़ने देना चाहिए, लेकिन फिर भी, अगर हम कोड लिख सकते हैं जो कि दोनों भाषाओं का समर्थन करता है, तो यह बेहतर है।
मैं उन अन्य लोगों से सहमत हूं जो इंगित करते हैं कि यदि आप चाहते हैं कि यह एक सच्चा सिंगलटन हो, जहां डेवलपर्स (गलती से) अपने स्वयं के उदाहरणों को unavailable
प्राप्त नहीं कर सकते हैं, तो क्वालिफायर चालू है init
और new
विवेकपूर्ण है।