ブロック内での自己の使用に困惑しています。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を使用しています
self
がブロックの参照を保持する場合は、self
への弱い参照のみを使用する必要があります。
あなたの例では、ブロックへの参照をself
に保持せず、UIView animateWithDuration:
でインラインでブロックを使用しているだけなので、__weak myViewController *weakSelf = self;
を使用する必要はありません。
これはなぜですか?ブロックは、ブロックを使用するクラスから使用する変数への強い参照を保持するためです。これにはself
が含まれます。これで、クラスインスタンス自体がブロックへの強い参照を保持し、ブロックがクラスインスタンスへの強い参照を保持する場合、保持サイクルが発生し、メモリリークが発生します。
@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
のObjectThatDoesNotRetainBlock
メソッドで、block
をivarとして作成しますが、block
がスコープ外になると、それへの参照。
test
メソッドでは、2つのオブジェクトがスコープから外れたときに、objectThatDoesNotRetainBlock
が保持サイクルの一部ではないため、割り当てが解除されていることに注意してください。
一方、objectThatRetainsBlock
は保持サイクルの一部であるため、割り当て解除されません。メソッド呼び出しの範囲を超えてブロックを保持します。
別の説明が必要な場合は、 この答え を参照してください。