2013-03-17 10 views
12

मैं उद्देश्य-सी में सिंगलटन को कार्यान्वित करने के तरीके के बारे में बहुत सारे धागे और ब्लॉग लेख पढ़ रहा हूं, उनमें से कई शायद थोड़ा बहिष्कृत (वर्ष 2010 या उससे पहले) हो रहा है, और ऐसा लगता है कि इस मुद्दे के बारे में लोगों के पास अलग-अलग राय हैं ... क्या ऐप्पल के पास सिंगलटन को लागू करने के बारे में दस्तावेज है? मुझे यह नहीं मिला। यदि हां, तो क्या कोई मुझे बता सकता है?आईओएस में उद्देश्य-सी सिंगलटन पैटर्न 5+

मुझे कक्षा के लिए सिंगलटन की आवश्यकता है जिसमें कुछ सार्वजनिक और निजी चर हैं। वर्तमान में, यह मेरे पास इस तरह के वर्ग के लिए कार्यान्वयन है:

@interface MySingleton() 
    @property (strong, nonatomic) NSString *state; 
@end 

@implementation MySingleton 

@synthesize state = _state; 
@synthesize count = _count; 

static MySingleton *sharedObject = nil; 

+ (MySingleton *)sharedInstance 
{ 
    static dispatch_once_t _singletonPredicate; 

    dispatch_once(&_singletonPredicate, ^{ 
     sharedObject = [[super allocWithZone:nil] init]; 
    }); 

    return sharedObject; 
} 

+ (id)allocWithZone:(NSZone *)zone 
{ 
    return [self sharedInstance]; 
} 

क्या यह अनुशंसित तरीका होना चाहिए? और मुझे आवृत्ति चर, सार्वजनिक और निजी कैसे प्रारंभ करना चाहिए?

एक और मुद्दा जो मैं सिंगलटन के बारे में स्पष्ट करना चाहता हूं: क्या यह स्मृति रिसाव उत्पन्न करेगा? आईओएस में वास्तव में सिंगलटन का उपयोग करने की सिफारिश की जाती है?

धन्यवाद

+0

वास्तव में ... क्या यह आईओएस 4 में काम करेगा? (जिज्ञासा के रूप में।) – Fattie

+0

और सहायक हो सकता है, यहां लोकप्रिय उत्तर में कोड की असाधारण सरल प्रस्तुति को नोट करें: http://codereview.stackexchange.com/questions/19829/objective-c-singleton-implementation – Fattie

उत्तर

3

Xcode में, के तहत 'खोज प्रलेखन' Creating a Singleton Instance दर्ज करें। बहुत सारे परिणाम हैं (लेकिन ऊपर दिए गए लिंक, पृष्ठ के निचले हिस्से में, उदाहरण कोड है)।

+9

मत हल्के ढंग से उस पृष्ठ के नीचे कोड का उपयोग करें। यह विशेष रूप से "सख्त सिंगलटन" के निर्माण के लिए है जैसा कि यह नोट करता है। कोको में ये बहुत दुर्लभ हैं। साझा सिंगलेट्स मानक हैं, और इस कोड के अधिकांश की आवश्यकता नहीं है। उस कोड स्निपेट ने नए कोको डेवलपर्स के बीच बहुत भ्रम पैदा किया है। मैं इसे अनदेखा करने की सलाह देते हैं; आप उन मामलों का सामना करने की संभावना नहीं हैं जहां यह उपयोगी है। –

1

हां, यह अनुशंसित तरीका है। मैं इसका उपयोग कैसे करता हूं इसका केवल एक छोटा सा अंतर है: मैं sharedObject को + (MySingleton *)sharedInstance विधि के अंदर स्थैतिक चर के रूप में परिभाषित करता हूं, क्योंकि गेटर विधि से कहीं और वैरिएबल तक पहुंचना संभव नहीं है।

और नहीं, आप मेमोरी रिसाव नहीं बनाएंगे। जब आपका ऐप समाप्त हो जाता है तो आपके ऐप द्वारा उपयोग की जाने वाली सभी आरक्षित मेमोरी को वैसे भी रिलीज़ किया जाएगा और कोई अन्य स्थिति नहीं है जहां एक स्थिर साझा उदाहरण जारी किया जाना चाहिए। प्री-एआरसी क्षेत्र में release विधि को ओवरराइड करने के लिए भी सामान्य था, वस्तु को गलती से जारी करने से रोकें।

+0

आपका मतलब है कि 'sharedObject' एक स्थिर चर होना चाहिए? –

+0

ओह, ज़ाहिर है। बस एक टाइपो था। इसे संपादित किया – miho

12

उपरोक्त सही है, @ मिहो की टिप्पणी साझाकरण विधि के अंदर स्थिर वस्तु को शामिल करने के बारे में टिप्पणी के साथ। लेकिन +allocWithZone: को ओवरराइड करने का कोई कारण नहीं है। ओबीजेसी में सिंगलेट्स आम तौर पर "साझा" नहीं होते हैं। आप "सिंगलटन" के अन्य उदाहरण बनाने के लिए स्वतंत्र हैं। यदि अन्य उदाहरण बनाना अवैध है, तो आपको init+allocWithZone: में कॉलर को बेवकूफ बनाने के बजाय NSAssert निष्पादित करना चाहिए। यदि आपका सिंगलटन उत्परिवर्तनीय है (और अधिकतर हैं), तो आपको बिल्कुल इस तरह +allocWithZone: ओवरराइड नहीं करना चाहिए।

एक और मुद्दा मैं सिंगलटन के बारे में स्पष्ट करना चाहता हूं: क्या यह स्मृति रिसाव उत्पन्न करेगा?

नहीं। यह वस्तु कभी जारी नहीं की जाएगी, लेकिन यह हमेशा पहुंच योग्य रहेगी। वह एक रिसाव नहीं है।

क्या आईओएस में वास्तव में सिंगलटन का उपयोग किया गया है?

हां, और यह एक बहुत ही आम पैटर्न है, जो पूरे कोको ढांचे में उपयोग किया जाता है। उस ने कहा, कई अन्य पैटर्न हैं जो हाल ही में डेवलपर्स के बीच कुछ हद तक लोकप्रिय हो गए हैं। निर्भरता इंजेक्शन कुछ हित प्राप्त कर रहा है, हालांकि मैं इसे अक्सर अभ्यास में नहीं देखता हूं। सिंगलेट्स पर आपकी निर्भरता को कम करने से टेस्टेबिलिटी में सुधार हो सकता है, और मैं हाल ही में प्रयोग कर रहा हूं कि कुछ सफलता के साथ मेरे कोड में उनमें से कुछ को कैसे खत्म किया जाए। लेकिन उनके पास कोको में एक लंबा, गर्व इतिहास है, और मैं उन्हें एक समस्या नहीं मानता।

संपादित करें: आपके कोड में एक वास्तविक बग है। आपको [[self alloc] init] पर कॉल करना चाहिए, [[super alloc] init] नहीं। +allocWithZone: पर कॉल करने का कोई कारण नहीं है, बस +alloc का उपयोग करें। (समय था जब ...WithZone: तरीकों उपयोगी लंबे बीत चुका है थे।) एकमात्र के लिए gcd का उपयोग कर चेतावनी के

+0

मुझे यह पूरी तरह से समझ में नहीं आता है, लेकिन बीएनआर आईओएस बुक में, वे '[[सुपर ऑलोक विथज़ोन: एनआईएल] init]' का उपयोग करते हैं और '+ allocWithZone:' में '[self SharedInstance]' वापस लौटाते हैं। वहां दिया गया कारण यह है कि 'एलोक' सिर्फ 'allocWithZone' कहता है: 'जो वास्तविक आवंटन करता है। '[सुपर allocWithZone]' का उपयोग करके मंडलियों में जा रहे कोड से बचा जाता है, जो अपनी 'allocWithZone' विधि को कॉल करता है। –

+2

आह। जब आप 'allocWithZone: '(जिसे आपको लगभग कभी ओवरराइड नहीं करना चाहिए) को ओवरराइड करना छोड़ दें, यह अब कोई समस्या नहीं होगी। –

+0

धन्यवाद! और फिर, "नियमित" कक्षाओं की तरह 'init' विधि को ओवरराइड करके वैरिएबल प्रारंभ किया जाना चाहिए? – AppsDev

0

यह है कि:

dispatch_once(&_singletonPredicate, ^{ 
     sharedObject = [[super allocWithZone:nil] init]; 
    }); 

यदि किसी कारण से init विधि प्रत्यक्ष या परोक्ष रूप सिंगलटन वस्तु को संबोधित करता है, वहाँ होगा एक डेडलॉक हो। इस कारण से मुझे विश्वास है कि एक सिंगलटन लिखने के लिए अधिक उपयुक्त तरीका

+ (void) initialize 

विधि

+1

इनिट विधि सिंगलटन इंस्टेंस का उपयोग क्यों करेगी? मैं एक ऐसे मामले की कल्पना नहीं कर सकता जहां वह होगा। जीसीडी जारी होने के बाद से 'प्रारंभिक' सिंगलेट लिखने का अधिक उचित तरीका नहीं है। (इससे पहले यह एक अच्छा तरीका था।) –

+0

हैलो, रोब :) मैं आपकी अद्भुत पुस्तक 'आईओएस डेवलपमेंट: द पुशिंग द लिमिट्स' के लिए ईमानदारी से धन्यवाद देना चाहता हूं, मैंने इससे एक टन सीखा! खैर, यह मेरे ऐप्स में से एक में हुआ है: init विधि ने किसी अन्य वर्ग के उदाहरण को तुरंत चालू किया, और दूसरे उदाहरण ने डिस्पैच_ऑन्स समाप्त होने से पहले सिंगलटन ऑब्जेक्ट को संबोधित किया (जो डेडलॉक का कारण बनता है)। हाँ, मुझे पता है कि डिजाइन दृश्य से यह बहुत अच्छा नहीं है :) – cpprulez

+0

बिल्कुल।आपके पास एक डिज़ाइन समस्या है, न कि सिंगलटन-पैटर्न समस्या। आप शायद init में बहुत ज्यादा कर रहे हैं। आप एक सिंगलटन का भी उपयोग कर सकते हैं जिसकी आपको आवश्यकता नहीं है। कभी-कभी लोग अकेले सिंगलटन में कूदते हैं, जब ऑब्जेक्ट को पास करना बेहतर होगा। –

0

मैं अभी भी उपयोग कर रहा हूँ CocoaWithLove से सिंगलटन हैडर thingy के माध्यम से है - थोड़ा दिनांकित किया जा सकता है, लेकिन अभी भी एक तरह काम करता है आकर्षण। यह मूल रूप से वर्णित है जैसा कि here एप्पल दस्तावेज़ों का जिक्र करता है और मुझे लगता है कि कम से कम ऐप्पल के दस्तावेज़ (bottom of this page) अभी भी मान्य हैं। लोग मानते हैं कि यह अनिश्चित काल तक वैध रहेगा, यह ऐप्पल का आधिकारिक समाधान है।

+0

हाय, हाँ, यह अभी भी मान्य है, हालांकि यह कुशल नहीं है, क्योंकि प्रत्येक बार सिंगलटन तक पहुंचने पर लॉक होता है, भले ही केवल एक थ्रेड इसे एक्सेस करने का प्रयास कर रहा हो। dispatch_once इस समस्या को हल करता है। – cpprulez

संबंधित मुद्दे