2012-04-08 11 views
5

मुझे नेट पर सिंगलटन पैटर्न मिला है। ऐसा लगता है कि इसमें कई चीजें हैं जिन्हें अनुकूलित किया जा सकता है।उद्देश्य-सी - इस सिंगलटन पैटर्न को अनुकूलित करना?

-sharedMySingleton विधि, बनाए रखने की आवश्यकता नहीं है? मुझे यकीन नहीं है ...
-अगर नहीं, allocWithZone में कोई रखरखाव क्यों है?
- @synchronized का उपयोग क्या है। NSAssert लगता है कि ब्लॉक में कई बार कहा जा सकता है, ताकि यदि हाँ, वहाँ पिछले स्मृति जारी है, या बस NSAsserting बिना स्पष्ट रूप से ब्लॉक बाहर निकलने के लिए कुछ और कोड होना चाहिए, और अगर नहीं, क्यों इस NSAssert है?
- श्रृंखला sharedMySingleton और alloc के बीच श्रृंखला अजीब लगती है। मैं अपने आप को कुछ तरह लिखा था:

+(MySingleton*)sharedMySingleton 
{ 
    @synchronized([MySingleton class]) 
    { 
     if (_sharedMySingleton == nil) _sharedMySingleton = [[self alloc] init]; 
     return _sharedMySingleton; 
    } 

    return nil; 
} 

+(id)alloc 
{ 
    @synchronized([MySingleton class]) 
    { 
     return [super alloc]; 
    } 

    return nil; 
} 

सिंगलटन पैटर्न

#import "MySingleton.h" 

@implementation MySingleton 

// ########################################################################################################## 
// ######################################## SINGLETON PART ################################################## 
// ########################################################################################################## 
static MySingleton* _sharedMySingleton = nil; 

// ================================================================================================= 
+(MySingleton*)sharedMySingleton 
// ================================================================================================= 
{ 
    @synchronized([MySingleton class]) 
    { 
     if (_sharedMySingleton == nil) [[self alloc] init]; 
     return _sharedMySingleton; 
    } 

    return nil; 
} 

// ================================================================================================= 
+(id)alloc 
// ================================================================================================= 
{ 
    @synchronized([MySingleton class]) 
    { 
     NSAssert(_sharedMySingleton == nil, @"Attempted to allocate a second instance of a singleton."); 
     _sharedMySingleton = [super alloc]; 
     return _sharedMySingleton; 
    } 

    return nil; 
} 

+ (id)allocWithZone:(NSZone *)zone { return [[self sharedMySingleton] retain]; } 
- (id)copyWithZone:(NSZone *)zone { return self; } 
- (id)retain      { return self; } 
- (NSUInteger)retainCount   { return NSUIntegerMax; /* denotes an object that cannot be released */} 
- (oneway void)release    { /* do nothing */ } 
- (id)autorelease     { return self; } 

// ########################################################################################################## 
// ########################################################################################################## 
// ########################################################################################################## 

// ================================================================================================= 
-(id)init 
// ================================================================================================= 
{ 
    if (!(self = [super init])) return nil; 

    return self; 
} 

// ================================================================================================= 
-(void) dealloc 
// ================================================================================================= 
{ 
    [super dealloc]; 
} 

// ================================================================================================= 
-(void)test 
// ================================================================================================= 
{ 
    NSLog(@"Hello World!"); 
} 

@end 

उत्तर

17

आप (सभी में इस पद्धति का उपयोग नहीं करना चाहिए यह सिंगलटन का एक बहुत ही विशेष मामले कि आप की आवश्यकता लगभग कभी नहीं के लिए है, और यहां तक ​​कि उस मामले में आपको आम तौर पर इसका उपयोग नहीं करना चाहिए)।

What should my Objective-C singleton look like? पर कई अच्छे पैटर्न चर्चा की गई हैं, लेकिन उनमें से अधिकतर जीसीडी के रिलीज के बाद पुरानी हैं। Mac तथा iOS के आधुनिक संस्करणों में, आप लिंक किए गए प्रश्न में निम्नलिखित पैटर्न, कॉलिन बैरेट द्वारा दिए गए का उपयोग करना चाहिए:

+ (MyFoo *)sharedFoo 
{ 
    static dispatch_once_t once; 
    static MyFoo *sharedFoo; 
    dispatch_once(&once, ^{ sharedFoo = [[self alloc] init]; }); 
    return sharedFoo; 
} 

मैं केवल इसे यहाँ नहीं बल्कि अंकन सवाल नकल से कॉपी क्योंकि पुराने प्रश्न के उच्चतम रेटेड जवाब बाहर दिनांकित हैं

+0

क्या अन्य तरीकों के बारे में: आपके पास होंगे, retaincount, रिहाई, copyWithZone, ...? आप "आधुनिक" संस्करणों के बारे में क्यों बात कर रहे हैं? आधुनिक से आपका क्या मतलब है? इस तरह के कोड के साथ ऐप्पल ने अपने सिंगलटन स्निपेट को अपडेट क्यों नहीं किया? – Oliver

+1

आधुनिक रूप से, मेरा मतलब है जीसीडी की शुरूआत के बाद से। आपको इन तरीकों को ओवरराइड नहीं करना चाहिए। केवल नमूना कोड है कि इन अधिभावी से पता चलता है यहाँ: https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/CocoaFundamentals/CocoaObjects/CocoaObjects.html यह नोट के रूप में, यह एक * सख्त * कार्यान्वयन है सिंगलटन का, जो ऊपर वर्णित पाठ आम तौर पर आवश्यक नहीं है। मैंने इस दस्तावेज़ को बेहतर बनाने के लिए एक डॉक्टर केस खोला है क्योंकि यह बहुत से डेवलपर्स को भ्रमित कर रहा है। माइक ऐश इस पर एक अच्छी पोस्ट है: http://www.mikeash.com/pyblog/friday-qa-2009-10-02-care-and-feeding-of-singletons.html –

+0

क्या में 10.6 के बराबर है आईओएस की शर्तें? – Oliver

0

retain पर कॉल करने की आवश्यकता नहीं है क्योंकि alloc है। इसके ऊपर retain पर कॉल करें मेमोरी लीक का कारण बन जाएगा। allocWithZone पर बनाए रखा गया है क्योंकि यह एक सिंगलटन है, इसलिए हम कक्षा के दो अलग-अलग उदाहरण नहीं बनाना चाहते हैं। एक नया उदाहरण आवंटित करने के बजाय हम सिंगलटन उदाहरण की बरकरार गिनती को बढ़ाते हैं। ऐसा क्यों है? शायद किसी को कक्षा के सिंगलटन प्रकार से अवगत नहीं होने से रोकने के लिए। वह allocWithZone कॉल और फिर उदाहरण जारी हैं, तो सब कुछ अभी भी ठीक से काम करते हैं, और वह वास्तव में साझा सिंगलटन उदाहरण पहुँचा।

@synchronized एक ही समय में अगर बयान में प्रवेश करने के लिए दो अलग-अलग धागे से दो कॉल को रोकने के लिए प्रयोग किया जाता है। तो कोड थ्रेड-सुरक्षित है।

NSSAssert शायद ऐप 'दुर्घटना' बनाने के लिए करता है, तो सिंगलटन के दो उदाहरणों कभी बनाई गई हैं है। यह 'बस-से-सुनिश्चित' कोड है, जिसे रक्षात्मक प्रोग्रामिंग भी कहा जाता है।

श्रृंखला के बारे में sharedMySingleton और alloc के बीच, मुझे लगता है कि यह ठीक है।

0

साझा माइसिंगलेटन विधि में, बनाए रखने की आवश्यकता नहीं है?

alloc एक के लिए एक संदर्भ गिनती के साथ एक नया उदाहरण देता है, इसलिए कोई बनाए रखने के लिए आवश्यक है।

यदि नहीं, तो allocWithZone में एक बरकरार क्यों है?

नियम अनुसार, जब आप allocWithZone कहते हैं, आप संदर्भ के मालिक हैं, इसलिए allocWithZone ज्यादा आप के लिए संदर्भ संख्या में वृद्धि। लेकिन allocWithZone का यह कार्यान्वयन सिंगलटन इंस्टेंस को वापस कर रहा है जो पहले से ही बनाया गया था और किसी और के स्वामित्व में था (sharedMySingleton विधि)। तो sharedMySingleton विधि ऑब्जेक्ट को alloc के साथ बनाता है, इसलिए यह एक मालिक बन जाता है। और फिर आपको allocWithZone के माध्यम से एक ही उदाहरण मिलता है, इसलिए आप एक ही उदाहरण के दूसरे मालिक बन जाते हैं। तो बरकरार गिनती बढ़नी चाहिए क्योंकि अब दो मालिक हैं। यही कारण है कि allocWithZone को बनाए रखने की जरूरत है।

@synchronized का उपयोग क्या है?

@synchronized एकाधिक धागे द्वारा कोड को एक साथ कॉल करने की अनुमति देता है। यदि आप कभी भी एक से अधिक धागे से sharedMySingleton पर कॉल नहीं करेंगे, तो यह आवश्यक नहीं है और आप इसे छोड़ सकते हैं।

NSAssert लगता है कि ब्लॉक में कई बार कहा जा सकता है, ताकि अगर हाँ, वहाँ कुछ और कोड जारी करने के लिए पिछले स्मृति, या बाहर निकलने के ब्लॉक स्पष्ट रूप से सिर्फ NSAsserting बिना होना चाहिए, और अगर नहीं, क्यों क्या यह एनएसएएसएसर्ट है?

क्योंकि वर्ग एक सिंगलटन होना करने का इरादा है, alloc केवल एक बार बुलाया जाना चाहिए। NSAssert() प्रोग्राम को समाप्त करता है यदि alloc को एक से अधिक बार बुलाया जाता है। चूंकि NSAssert() कार्यक्रम समाप्त हो जाता है, जब alloc दूसरी बार कहा जाता है, कोई स्मृति प्रबंधन के लिए आवश्यक है।

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