2012-11-02 8 views
43

मैं स्वयं के अंदर के ब्लॉक के उपयोग से भ्रमित हो रहा हूं, मैं ऐप्पल के कुछ दस्तावेजों से गुजरता हूं लेकिन अभी भी सही जवाब नहीं मिल रहा है।क्या हमेशा ब्लॉक के अंदर स्वयं को कमजोर संदर्भों का उपयोग करना आवश्यक है ..?

कुछ लोगों को हमेशा ब्लॉक के अंदर कमजोर स्वयं का प्रयोग करते हैं, लेकिन कुछ ब्लॉकों कि कॉपी कर रहे हैं, हमेशा उपयोग करने के लिए neassary नहीं में कमजोर स्वयं प्रयोग करते हैं।

नमूना 1:

self.handler = ^(id response, NSError *error) 
{ 
    self.newresponse = response; //use weak self here 
}; 

नमूना 2:

कमजोर स्वयं का उपयोग करना;

__weak myViewController *weakSelf = self; 

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^ 
{ 
    [weakSelf.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)]; 
    //in above is it use of weak is neassary 
} 
completion:^(BOOL finished) 
{ 

}]; 

कमजोर स्वयं के बिना;

__weak myViewController *weakSelf = self; 

[UIView animateWithDuration:interval delay:0.0 options:curve animations:^ 
{ 
    [myViewController.view.superview setTransform:CGAffineTransformMakeTranslation(0, -106)]; 

} 
completion:^(BOOL finished) 
{ 

}]; 

उपरोक्त नमूने में, जो सही हैं ...? ** मैं एआरसी

+0

\ _ \ _ कमजोर ऑब्जेक्ट (आईओएस 5 + एआरसी) के बिना ब्लॉक में संभवतः [[स्वयं किसी भी समारोह \] को पास करने के संभावित संभव डुप्लिकेट (http://stackoverflow.com/questions/9003600/possible-to-pass- स्वयं-असफलता-इन-ब्लॉकों-बिना-कमजोर-ऑब्जेक्ट-आईओएस -5-आर्क) – Abizern

+0

http://stackoverflow.com/questions/20030873/always-pass-weak-reference-of-self-into का डुप्लिकेट -ब्लॉक-इन-आर्क –

उत्तर

73

का उपयोग कर रहा हूं, आपको self के लिए कमजोर संदर्भ का उपयोग करना चाहिए, यदि self ब्लॉक के संदर्भ में होगा।

अपने उदाहरण में, आप self में अपने ब्लॉक के लिए एक संदर्भ रखने नहीं कर रहे हैं, तो आप केवल ब्लॉक इनलाइन UIView animateWithDuration: साथ प्रयोग कर रहे हैं, और इस तरह के रूप __weak myViewController *weakSelf = self;

क्यों यह मामला है उपयोग करने के लिए कोई जरूरत नहीं है? चूंकि ब्लॉक ब्लॉक का उपयोग करके कक्षा से उपयोग किए जाने वाले किसी भी चर के मजबूत संदर्भ बनाए रखेगा। इसमें self शामिल है। अब यदि क्लास इंस्टेंस ब्लॉक के लिए एक मजबूत संदर्भ रखता है, और ब्लॉक क्लास इंस्टेंस के लिए एक मजबूत संदर्भ रखता है, तो आपके पास एक सतत चक्र होता है, जिससे मेमोरी लीक का कारण बनता है।

typedef void (^SimpleBlock)(); 

@interface ObjectThatRetainsBlock : NSObject 
@property(nonatomic, strong) SimpleBlock block; 
@end 

@implementation ObjectThatRetainsBlock 

- (instancetype)init { 
    self = [super init]; 
    if (self) { 
    self.block = ^{ NSLog(@"Running block in %@", self); }; 
    self.block(); 
    } 
    return self; 
} 

- (void)dealloc { 
    NSLog(@"ObjectThatRetainsBlock is deallocated."); 
} 

@end 

@interface ObjectThatDoesNotRetainBlock : NSObject 
@end 

@implementation ObjectThatDoesNotRetainBlock 

- (instancetype)init { 
    self = [super init]; 
    if (self) { 
    SimpleBlock block = ^{ NSLog(@"Running block in %@", self); }; 
    block(); 
    } 
    return self; 
} 

- (void)dealloc { 
    NSLog(@"ObjectThatDoesNotRetainBlock is deallocated."); 
} 

@end 

- (void)test { 
    ObjectThatRetainsBlock *objectThatRetainsBlock = 
     [[ObjectThatRetainsBlock alloc] init]; 
    ObjectThatDoesNotRetainBlock *objectThatDoesNotRetainBlock = 
     [[ObjectThatDoesNotRetainBlock alloc] init]; 
} 

test विधि प्रिंट:

+3

इसलिए क्लास विधि (एनिमेट विथडिशन) में कमजोर आत्म की आवश्यकता नहीं है क्योंकि स्वयं उस ब्लॉक को बनाए रखने या स्वामित्व में नहीं है, क्या मैं सही हूं ...? – ShivaPrasad

+0

नमूना 1 self.handler =^(आईडी प्रतिक्रिया, एनएसईआरआर * त्रुटि) { self.newresponse = प्रतिक्रिया; // कमजोर स्वयं का उपयोग करें }; हमें हफ्ते की जरूरत है क्योंकि ब्लॉक स्वयं को बनाए रखता है और स्वयं ब्लॉक द्वारा बनाए रखा जाता है, इसलिए यह चक्र बनाए रखता है ...? – ShivaPrasad

+5

@jeeva नमूना 1 में, स्वयं ** के लिए एक कमजोर संदर्भ ** आवश्यक है। नमूने 2 और 3 में, स्वयं ** के लिए एक कमजोर संदर्भ ** आवश्यक नहीं है। – WDUK

10

यहाँ कुछ कोड है कि यह दर्शाता है @ WDUK का जवाब है

Running block in <ObjectThatRetainsBlock: 0x7f95f3335e50> 
Running block in <ObjectThatDoesNotRetainBlock: 0x7f95f3335c50> 
ObjectThatDoesNotRetainBlock is deallocated. 

गौर करें कि ObjectThatDoesNotRetainBlock की init विधि में, हम एक इवर रूप block बनाने के लिए, लेकिन जब block गुंजाइश से बाहर चला जाता है, हम इसका संदर्भ नहीं रखते हैं।

test विधि में, जब दोनों वस्तुएं गुंजाइश से बाहर जाती हैं, तो देखें कि objectThatDoesNotRetainBlock को हटा दिया गया है क्योंकि यह एक बनाए रखने चक्र का हिस्सा नहीं है।

दूसरी ओर, objectThatRetainsBlock deallocated नहीं मिलता है, क्योंकि यह एक चक्र को बनाए रखने का हिस्सा है। यह विधि कॉल के दायरे से परे ब्लॉक को बरकरार रखता है।

आप एक एक और स्पष्टीकरण चाहते हैं, this answer देखते हैं।

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