2012-02-11 10 views
8

मैं एआरसी के बारे में थोड़ा पढ़ रहा था @autoreleasepool का उपयोग करें और करने के लिए जब मैं इस देखा:उद्देश्य सी - - एआरसी

@interface Address : NSObject { 
    @public 
    NSString *city; 
} 
@end 

@implementation Address 
- (Address*) init: (NSString*) c { 
    city = c; 

    return self; 
} 

- (void) dealloc { 
    NSLog(@"Destroying address: %@", city); 
} 
@end 

@interface Customer : NSObject { 
    NSString *name; 
    Address *addr; 
} 
@end 

@implementation Customer 
- (Customer*) init: (NSString*) n withAddress: (Address*) a { 
    //Note 1: Automatic retain on assignment 
    name = n; 
    addr = a; 

    return self; 
} 

- (void) dealloc { 
    NSLog(@"Destroying: %@", name); 
    //Note 2: Automatic release of member variables 
} 

@end 

Customer* objectReturnTest() { 
    NSString * n = [[NSString alloc] initWithString: @"Billy Bob"]; 
    Address * a = [[Address alloc] init: @"New York City"];  

    Customer *c = [[Customer alloc] init: n withAddress: a]; 

    //Note 3: ARC will put the returned object in autorelease pool. 
    return c; 
} 

A couple of basic things to note here. As "Note 1" says, when an object is assigned to a variable, a call to retain is made automatically. This increments the reference count. As "Note 2" says, when an object is destroyed, all member variable objects are released for you. You no longer have to do that from the dealloc method. 

Finally, when a method returns a newly created object, ARC will put the returned object in an autorelease pool. This is stated in "Note 3". 

Now, let’s use the code. 

int main (int argc, const char * argv[]) 
{ 
    NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"]; 
    Address * a = [[Address alloc] init: @"Miami"]; 
    Customer *c = [[Customer alloc] init: n withAddress: a]; 

    NSLog(@"Before force release"); 
    c = nil; //Force a release 
    NSLog(@"After force release"); 

    @autoreleasepool { 

     Customer *c2 = objectReturnTest(); 

    } 
    NSLog(@"After autorelease pool block."); 

    return 0; 
} 

The log output from this code will be: 

Before force release 

Destroying: Johnny Walker 

After force release 

Destroying: Billy Bob 

Destroying address: New York City 

After autorelease pool block. 

Destroying address: Miami 

A couple of things to note here. See how force release works. We set a variable to nil. ARC immediately releases the reference count. This causes the Customer object "Johnny Walker" to get destroyed. But, the member Address object "Miami" doesn’t get destroyed. This object gets destroyed at the very end of the main method. This is an extremely odd and non-intuitive behavior. Technically, this is not a memory leak, but, in reality member variables can pile up and take up a lot of memory. This is just as bad as memory leak. 

The object return test works as expected. Customer "Billy Bob" is put in auto release pool. At the end of the @autoreleasepool block, the pool is drained and the object is released. 

इस भाग को देखते हुए;

int main (int argc, const char * argv[]) 
{ 
    NSString * n = [[NSString alloc] initWithString: @"Johnny Walker"]; 
    Address * a = [[Address alloc] init: @"Miami"]; 
    Customer *c = [[Customer alloc] init: n withAddress: a]; 

    NSLog(@"Before force release"); 
    c = nil; //Force a release 
    NSLog(@"After force release"); 

    @autoreleasepool { 

     Customer *c2 = objectReturnTest(); 

    } 
    NSLog(@"After autorelease pool block."); 

    return 0; 
} 

जब वह सी = शून्य करता है; सी और एन को नष्ट नहीं किया जाना चाहिए? फिर भी यह कहता है कि आउटपुट केवल इतना है कि एन नष्ट हो गया है .. क्या कोई समझा सकता है क्यों?

और वह कहता है कि परिणाम स्मृति रिसाव के रूप में खराब है, तो आप इसे कैसे ठीक करते हैं?

और एक आखिरी सवाल, आप @autoreleaasepool का उपयोग कब करना चाहिए?

+0

आप इसे कहां पढ़ रहे थे? –

+0

http://blog.webagesolutions.com/ – user1021085

उत्तर

10
लाइन द्वारा

c = nil; //Forces a release 

एक Customer उदाहरण तो एक परिणाम के रूप उत्पादन

को नष्ट है पुनः आवंटित की जाती है क्योंकि कोई भी यह बनाए रखना है,: जॉनी वॉकर

लेकिन n और a को हटाया नहीं गया है क्योंकि वे अभी भी दायरे में रहते हैं और nil उन्हें सौंपा नहीं गया है।

और मैं यह नहीं लगता कि रिसाव स्मृति के किसी भी प्रकार है


आप सामान्य रूप से @autorelasepool उपयोग करने के लिए जब तक आप इस

- (void)myMethod { 
    for (int i = 0; i < 1000000; i++) { 
     NSString *string = [NSString stringWithFormat:@"%d", i]; 
     // do something with string 
    } 
} 

1000000 से NSString की तरह कुछ कर रहे हैं की जरूरत नहीं है लूप के दौरान आवंटित किया जाएगा। विधि वापस लौटने के बाद उन्हें हटा दिया जाएगा (वास्तव में इस रनलोप के बाद) लेकिन पहले से ही बहुत अधिक स्मृति का उपभोग करते हैं। आप इस पढ़ना चाहिए इसलिए

- (void)myMethod { 
    for (int i = 0; i < 1000000; i++) { 
     @autoreleasepool { 
      NSString *string = [NSString stringWithFormat:@"%d", i]; 
      // do something with string 
     } 
    } 
} 

को बदलना चाहिए स्मृति प्रबंधन https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmAutoreleasePools.html#//apple_ref/doc/uid/20000047-CJBFBEDI

+0

जब आप स्ट्रिंग घोषित करते हैं तो क्या आप autorelease नहीं जोड़ना चाहिए? – user1021085

+1

और बस एक और बात, क्या होगा यदि आप एक स्ट्रिंग की तरह कुछ काम वापस करना चाहते हैं? क्या आप बस एनएसएसटींग * ए = @ "हे" करते हैं; एक वापसी ;? एक डिलीकेट नहीं किया जाएगा और आप मूल्य को बचाने में सक्षम नहीं होंगे? – user1021085

+0

@ user1021085 '[एनएसएसटींग स्ट्रिंग विथफॉर्मैट:] 'यह' [[[एनएसएसटींग एलोक] initWithFormat:] autorelease] के समान है, इसलिए यह एक ऑटोरेलेज्ड ऑब्जेक्ट है।एआरसी सब कुछ संभाल सकता है (जब तक कि आप __unsafe_unretained पॉइंटर या __bridge कास्ट से निपट नहीं रहे हैं) तो यह स्ट्रिंग को बनाए रखेगा और ऑटोरलीज करेगा और इसे अगले रनलोप –

1

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

तो जब आप पते के लिए इस सार्वजनिक मूल्य को कॉल करते हैं तो यह अभी भी वहां है, लेकिन नाम के लिए एनएसएसटींग नहीं है। इसे ठीक करने के लिए आप या तो पता ऑब्जेक्ट का इंटरफ़ेस हटाते हैं, जो दोनों मानों को जारी करता है या आप NSString का उपयोग करने के बजाय नाम के लिए एक इंटरफ़ेस बनाते हैं।

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