ARC環境のObjective-Cでブロック内でインスタンス変数にアクセスする場合のメモ。
ポインタ変数ならば__block修飾子を使ってretain cycleを回避すればいいのだけど、変数が整数や真偽値などのプリミティブ型だった場合機能しないので以下のように参照を使う。
main.m
@interface SomeClass () {
BOOL _flag;
}
main.m
[self performBlock:^(id sender) {
// retain cycle が起きる
_flag = YES;
} afterDelay:(NSTimeInterval)]
main.m
__block BOOL __flag = _flag
[self performBlock:^(id sender) {
// ポインタではないので機能しない
__flag = YES;
} afterDelay:(NSTimeInterval)]
※Ushioさんのご指摘を受けたため修正しました。
ブロック内にインスタンス変数へのポインタをキャプチャしてしまうとselfが破棄されたかどうかの判断がつかないそうです。以下は、KVアクセッサを使ってインスタンス変数にブロック内でアクセスする方法です。
main.m
__block __weak typeof(self) __self = self;
[self performBlock:^(id sender) {
// KV使ってインスタンス変数にアクセスする
[__self setValue:YES forKey:@"_flag"];
BOOL flag = [__self valueForKey:@"flag"] boolValue];
} afterDelay:(NSTimeInterval)]