7

NSObject पद्धति का उपयोग करना -(id)awakeAfterUsingCoder:(NSCoder *)decoder एक उदाहरण के रूप, प्रलेखन कहते हैं:स्वत: संदर्भ गणना के साथ स्वयं को जारी करने के लिए नया पैटर्न क्या है?

एक वस्तु की अनुमति देता है, डीकोड किए जाने के बाद, खुद के लिए किसी अन्य वस्तु विकल्प। उदाहरण के लिए, एक ऑब्जेक्ट जो फ़ॉन्ट का प्रतिनिधित्व करता है, पर डीकोड किया जा रहा है, खुद को छोड़ दें और अपने जैसा ही फ़ॉन्ट विवरण स्वयं मौजूद एक मौजूदा ऑब्जेक्ट को वापस कर दें। इस तरह, अनावश्यक वस्तुएं समाप्त हो सकती हैं।

आम तौर पर आप

[self release]; 
return substitutedObject; 
एआरसी के साथ

कर आप इस लाइन को छोड़ना होगा। यह रिसाव नहीं होगा? या मुझे सिर्फ मेरे लिए मूल वस्तु जारी करने के लिए एनएससीओडर ऑब्जेक्ट पर भरोसा करना चाहिए? यदि ऐसा है तो आपको पहले स्थान पर स्वयं को गैर-एआरसी कोड के साथ स्पष्ट रूप से क्यों रिलीज़ करना होगा?

मुझे नहीं लगता कि self = nil क्या संकलक प्रलेखन स्वयं के बारे में कहते हैं की रोशनी में सही है: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#misc.self

उत्तर

2

के रूप में बताया गया है, आप [self release]; नहीं लिख सकते हैं। इसके अतिरिक्त, awakeAfterUsingCoder:प्रारंभिक नहीं है - आप self को पुन: असाइन नहीं कर सकते हैं।

इस रिसाव नहीं चाहेंगे?

हां। नीचे कार्यक्रम में प्रख्यात।

या मुझे सिर्फ मेरे लिए मूल वस्तु को जारी करने के लिए एनएससीओडर ऑब्जेक्ट पर भरोसा करना चाहिए?

सं

एक दृष्टिकोण रिसाव से बचने के लिए नीचे मौजूद है - मैं इसे "नए पैटर्न" कॉल नहीं होता, सिर्फ पहला दृष्टिकोण है कि दिमाग में आया था। यह self की एक स्पष्ट रिहाई शामिल है और इस मामले में एक स्पष्ट परिणाम की को बनाए रखें:

#import <Foundation/Foundation.h> 

@interface MONBoolean : NSObject <NSCoding> 

- (id)initWithBool:(bool)pBool; 

- (bool)isTrue; 
- (bool)isFalse; 

@end 

static NSString * const MONBoolean_KEY_value = @"MONBoolean_KEY_value"; 

@implementation MONBoolean 
{ 
    bool value; 
} 

- (id)initWithBool:(bool)pBool 
{ 
    self = [super init]; 
    if (0 != self) { 
     value = pBool; 
    } 
    return self; 
} 

- (bool)isTrue 
{ 
    return true == value; 
} 

- (bool)isFalse 
{ 
    return false == value; 
} 

- (NSString *)description 
{ 
    return [[NSString alloc] initWithFormat:@"<%s:%p> : %s", object_getClassName(self), self, self.isTrue ? "true" : "false"]; 
} 

- (void)encodeWithCoder:(NSCoder *)aCoder 
{ 
    [aCoder encodeBool:value forKey:MONBoolean_KEY_value]; 
} 

- (id)initWithCoder:(NSCoder *)aDecoder 
{ 
    self = [super init]; 
    if (0 != self) { 
     value = [aDecoder decodeBoolForKey:MONBoolean_KEY_value]; 
    } 
    return self; 
} 

- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder 
{ 
    const bool b = value; 
    // cannot reassign self outside of an initializer. 
    // if not released, will result in a leak: 
    CFRelease((__bridge const void*)self); 
    MONBoolean * result = [[MONBoolean alloc] initWithBool:b]; 
    // now we have to retain explicitly because this is 
    // an autoreleasing method: 
    CFRetain((__bridge const void*)result); 
    return result; 
} 

@end 

int main(int argc, const char * argv[]) 
{ 
    @autoreleasepool { 
     MONBoolean * a = [[MONBoolean alloc] initWithBool:true]; 
     NSData * data = [NSKeyedArchiver archivedDataWithRootObject:a]; 
     MONBoolean * b = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 
     NSLog(@"%@", b); 
    } 
    system("leaks NAME_OF_PROCESS_HERE"); 
    return 0; 
} 
+0

क्या आप स्पष्ट कर सकते हैं कि आपको स्पष्ट रूप से परिणाम क्यों बनाए रखना है? निश्चित रूप से एआरसी के उद्देश्य को हरा देता है। बाकी सब कुछ जवाब देने के लिए धन्यवाद। – jamesmoschou

+0

@moshy आपका स्वागत है। हाँ - मैंने शुरुआत में उस विवरण को अनदेखा कर दिया। इसका कारण यह है कि 'जागृत करने के बाद कोडर:' एक गैर-स्वामित्व (या स्वत: समाप्त) संदर्भ देता है। इस प्रकार, एआरसी हमारे रिटर्न वैल्यू के लिए हमारे लिए एक रेफ-गिनती कमी दर्ज करता है। हम जो करना चाहते हैं वह प्रभावी रूप से * स्थानांतरण * एक ऑब्जेक्ट से दूसरे ऑब्जेक्ट में संदर्भ है। मैं इसे उपकरणों में चला गया - कोई रिसाव नहीं। कोई लाश नहीं स्पष्ट बनाए रखने के बिना, एक ज़ोंबी संदेश भेजा जाएगा। स्पष्ट रिलीज के बिना - एक रिसाव। इसे अपने लिए आज़माएं ('@ autorelease' ब्लॉक को 'जबकि (1)' में रखें)। – justin

+1

क्या आप विधि 'itattribute __ ((objc_method_family (init)) ('objc_method_family (init)) के साथ' init' परिवार का सदस्य बना सकते हैं) 'और फिर' self' को फिर से सौंपें? –

0

मेरा मानना ​​है कि एआरसी सभी वस्तुओं का ट्रैक रखने के लिए पर्याप्त चतुर है। इसलिए आपको स्मृति के बारे में कुछ भी नहीं कहना चाहिए और ऐप ऑब्जेक्ट को तब रिलीज़ करेगा जब यह अब उपयोग में नहीं है। लीक प्रोफाइलर के माध्यम से इसे चलाएं, बस मामले में, लेकिन यह ठीक होना चाहिए।

+4

लेकिन मेरी समझ यह थी कि स्वत: संदर्भ गणना अभी भी संदर्भ गणना है। यह कचरा संग्रह के समान नहीं है। इसलिए यह अभी भी (सैद्धांतिक रूप से) संभव है जब वे अब उपयोग में नहीं हैं। मैं इसे प्रोफाइलर के माध्यम से चलाऊंगा। – jamesmoschou

4

Mac OS X पर निब उच्च-स्तरीय वस्तुओं के संदर्भ में ऐसा ही एक मुद्दा उठता है Resource Programming Guide का कहना है:

तो फ़ाइल के मालिक NSWindowController या NSViewController का एक उदाहरण नहीं है, तो आप संदर्भ गिनती घटती करने के शीर्ष स्तर अपने आप वस्तुओं की जरूरत है। मैन्युअल संदर्भ गिनती के साथ, शीर्ष स्तर की वस्तुओं को release संदेश भेजकर इसे प्राप्त करना संभव था। आप एआरसी के साथ ऐसा नहीं कर सकते हैं। इसके बजाए, आपने कोर फाउंडेशन प्रकार के लिए शीर्ष-स्तरीय ऑब्जेक्ट्स के संदर्भ डाले और CFRelease का उपयोग किया।

तो, इस तकनीक का संभवतः इस स्थिति में भी उपयोग किया जा सकता है। CFRelease((__bridge CFTypeRef)self);

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