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を使用しています

4

2 に答える 2

76

ブロックの参照を保持するself場合は、への弱参照のみを使用する必要があります。self

あなたの例では、でブロックへの参照を保持しておらず、でselfインラインのブロックのみを使用しているためUIView animateWithDuration:、を使用する必要はありません。__weak myViewController *weakSelf = self;

なぜそうなのですか?ブロックは、ブロックを使用するクラスから使用する変数への強力な参照を保持するためです。これにはが含まれselfます。これで、クラスインスタンス自体がブロックへの強力な参照を保持し、ブロックがクラスインスタンスへの強力な参照を保持する場合、保持サイクルが発生し、メモリリークが発生します。

于 2012-11-02T11:59:09.563 に答える
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.

initメソッドでは、ivarとしてObjectThatDoesNotRetainBlock作成しますが、スコープ外になると、それへの参照を保持しないことに注意してください。blockblock

このtestメソッドでは、2つのオブジェクトがスコープ外にobjectThatDoesNotRetainBlockなると、保持サイクルの一部ではないため、割り当てが解除されていることを確認します。

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

別の説明が必要な場合は、この回答を参照してください。

于 2015-04-05T18:30:34.737 に答える