2012-11-02 10 views
43

私は内部のブロックの使用と混同されています。私はAppleのドキュメントのいくつかを調べても、正しい答えを見つけることはできません。自己内部の弱い参照を常にブロック内で使用する必要がありますか?

一部の人々は、常に弱い自己内部ブロックを使用すると言いますが、コピーされたブロックでは弱い自己を使用し、常に使用することはありません。

サンプル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) 
{ 

}]; 

正しいサンプルは...? **私はARCを使用しています

+0

可能な複製[\ [self anyFunction \]を\ _ \ _弱いオブジェクト(iOS 5 + ARC)のないブロックで渡すことができる](http://stackoverflow.com/questions/9003600/possible-to-pass- weak-object-ios-5-arcなしのブロック内自己自己機能) – Abizern

+0

また、http://stackoverflow.com/questions/20030873/always-pass-weak-reference-of-self-intoの複製-block-in-arc –

答えて

73

selfがブロックの参照を保持する場合は、selfに弱参照のみを使用してください。あなたの例では

、あなたがselfであなたのブロックへの参照を保持していない、あなただけのUIView animateWithDuration:とインラインブロックを使用している、そのように__weak myViewController *weakSelf = self;

なぜこのような場合はを使用する必要はありませんか?ブロックは、ブロックを使用するクラスから使用するすべての変数への強い参照を保持するためです。これにはselfが含まれます。現在、クラスインスタンス自体がブロックへの強い参照を保持し、ブロックがクラスインスタンスへの強い参照を保持している場合、保持リークが発生し、メモリリークが発生します。ここで

+3

クラスメソッド(animateWithDuration)では、自己がそのブロックを保持または所有していないので弱い自己の必要はありません。 – ShivaPrasad

+0

サンプル1でself.handler = ^(IDレスポンス、NSError *エラー) { self.newresponse = response; //ここで弱い自己を使う };ブロックは自己によって保持され、自己はブロックによって保持されるので、我々は週自己が必要なので、それは保持サイクルである...? – ShivaPrasad

+5

@jeevaサンプル1では、自己**への弱い参照が必要です**。サンプル2とサンプル3では、自己**への弱い参照は必要ない**。 – WDUK

10

はWDUKの答え@実証いくつかのコードです:

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方法を印刷:

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

ObjectThatDoesNotRetainBlockinit方法では、我々はIVARとしてblockを作成するのではなく、ときことを確認しblockは範囲外になり、その参照を保持しません。

メソッドでは、2つのオブジェクトが有効範囲外になると、保持サイクルの一部ではないため、objectThatDoesNotRetainBlockが割り当て解除されることがわかります。

一方、objectThatRetainsBlockは、保持サイクルの一部であるため、割り当て解除されません。メソッド呼び出しの範囲を超えたブロックを保持します。

その他の説明については、this answerを参照してください。

関連する問題