私はこのスレッドを読みました: 「__ block」キーワードの意味は何ですか? これは__block
が使用されていますが、答えの1つについて混乱しています。 __block
は保持サイクルを回避するために使用されますが、その下のコメントは不確かです。
私はそれを次のように使用しています:
self.someProperty = x; //where x is some object (id)
__block __weak VP_User *this = self;
//begin a callback-style block
this.someProperty = nil;
両方を使用する必要がありますか__block
および__weak
?これがこのように見えることで明白な問題はありますか?
__block
はストレージ修飾子です。変数をコピーするのではなく、ブロックで直接キャプチャする必要があることを指定します。これは、次の例のように、元の変数を変更する必要がある場合に役立ちます。
__block NSString *aString = @"Hey!";
void(^aBlock)() = ^{ aString = @"Hello!" }; // without __block you couldn't modify aString
NSLog(@"%@", aString); // Hey!
aBlock();
NSLog(@"%@", aString); // Hello!
ARCでは、これにより変数が自動的に保持されるため、ブロック実装内で安全に参照できます。前の例では、ブロックコンテキストでキャプチャされると、aString
にretain
メッセージが送信されます。
これは、変数が保持されずに参照されるMRC(手動参照カウント)では当てはまりません。
__weak
としてマークすると、変数は保持されないため、ブロックはそれを直接参照しますが、保持しません。これは、ブロックが変数よりも長く存続する場合、ガベージメモリを参照するため(そしてクラッシュする可能性が高いため)、潜在的に危険です。
clang doc の関連する段落を次に示します。
Objective-CおよびObjective-C++言語では、オブジェクトタイプの
__weak
変数に対して__block
指定子を使用できます。 [...]この修飾子により、これらの変数は、送信されるメッセージを保持せずに保持されます。これは、ブロック(またはコピー)がこのオブジェクトの存続期間よりも長く存続する場合、故意にダングリングポインターにつながります。
最後に、__block
を使用して強い参照サイクル(別名保持サイクル)を回避できるという主張は、ARCコンテキストでは明らかに間違っています。 ARCでは__block
によって変数が強く参照されるため、実際にはその可能性が高くなります。
たとえばMRCでは、このコードは保持サイクルを中断します
__block typeof(self) blockSelf = self; //this would retain self in ARC!
[self methodThatTakesABlock:^ {
[blockSelf doSomething];
}];
aRCで同じ結果を得るには、通常、
__weak typeof(self) weakSelf = self;
[self methodThatTakesABlock:^ {
[weakSelf doSomething];
}];
ブロック内の変数値を変更する場合は、__block
を使用する必要があります。
例えば:
__block BOOL result = NO;
dispatch_sync(dispatch_get_main_queue(), ^{
...
result = YES;
...
});
保持サイクルを回避する場合は、__weak
を使用する必要があります。
例えば。:
__weak typeof(self) wself = self;
self.foobarCompletion = ^{
...
wself.foo = YES;
...
};
必要に応じて組み合わせることができます。