web-dev-qa-db-ja.com

ブロックは暗黙的に「自己」を保持します。 -しかし、それは意図された動作ですか?

昨日、私の最新のiOSビルドはXcodeで警告なしで実行されました。バージョン9.3(9E145)に一晩アップグレードした後、複数の警告が表示されました。同様の質問に対して answer(1) に従ってself->scoreを試したところ、警告が消えました。

しかし、より最近の answer(2) 同じ質問に対して、設定を変更することで問題が解決されます。現在、Apple LLVM 9.0 - Warnings -Objective C and ARCの私の設定は

ブロック内の「自己」の暗黙的な保持

しかし、私はBlock implicitly retains 'self'がコードのコンテキストで何を意味するのか理解していない以下ので、この動作が正しいかどうかはわかりません'意図されました'。または、問題を解決したか、単にそれを隠したか。または、回答1が回答2よりも優れているかどうか。

このコンテキストでのBlock implicitly retains 'self'の意味を誰かが親切に説明してくれませんか?ありがとう。

score.alpha = 1.0;

if (sequenceState >= STATES_Count)
{
    [GraphicScore animateWithDuration:8.0f
                                delay:1.0f
                              options:UIViewAnimationOptionCurveEaseOut
                           animations:^{self->score.alpha = 0.0;} // animations:^{score.alpha = 0.0;}
                           completion:^(BOOL finished){ }];
}
[self addSubview:score];
9
Greg

selfへの暗黙的な参照に関するこの警告は、コードがない場合、強い参照サイクルを導入するリスクがあるブロックとそうでないブロックが必ずしも明確ではないため、役に立ちます。プログラマーにこれらのself参照を明示的にするように促すことで(Swiftなどの安全なプログラミング言語で必要とされるように)、強力な参照サイクルが潜在的な問題であるかどうかを明確に確認できるコードができあがります。

したがって、警告をオンにしたまま、これらの暗黙のself参照(ivars)をself->またはプロパティを使用する場合はself.で明示的にすることをお勧めします。あなたが参照した最初の回答でアドバイスされているように。

次に、selfクロージャーの個別の使用を確認し、強い参照サイクルの実際のリスクを引き起こさないことを確認できます。そして、もしそうなら、あなたはweakSelfまたはweakSelf/strongSelfパターンを適切に採用することができます。

18
Rob

与えられた:

- (void)bobIsYourUncle {
   ^{score.alpha = 0.0;}();
}

ここで、scoreは、selfを介してアクセスされるインスタンス変数です。ブロックはどこかでキューに入れられ、後で実行される可能性があるため、ブロックが作成されたとき、ブロックはselfを保持します。

Ivarアクセス​​非表示selfを介して逆参照するため、その暗黙の保持はコードでははっきりとわかりません。コンパイラがivarの前にself->を追加するというやや醜い提案は、少なくともselfがブロックによってキャプチャされていることを明らかにしています。

だから、はい、それは正しい動作です。そして、はい、それはいつか望まれています。 (ローカル変数で)ブロックが作成される前にivarの値を取得することで回避できますが、そうすることも知っておく必要がありますivarの値が取得される時間を変更します行動の変化。

3
bbum