オブジェクトが操作の完了ブロックで参照されている場合、オブジェクトがネットワーク操作を取り消すことが良い考えであるかどうかを理解しようとしています。
例を挙げて説明します。
プロパティを持つUser
オブジェクトがあり、次のものがあります。 picture
User
[self fetchPictureFromServer]
- (void)fetchPictureFromServer
{
NSDictionary *cmdParameters = ...; // set parameters
__block User *weakSelf = self;
[[AppClient sharedClient] sendCommand:@"getpicture" parameters:cmdParameters success:^(AFHTTPRequestOperation *operation, id response)
{
// success
UIImage *downloadedImage = ...; // get image from response
weakSelf.picture = downloadedImage; // set image to user's picture property
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
// failed
}];
このsendCommand
メソッドは を作成 (および にキューに登録NSOperationQueue
) し、NSOperation
それがやがて を開始しNSURLConnection
てイメージをダウンロードします。操作が正常に完了すると、成功ブロックが呼び出されます。
私が使用してweakSelf
いるのは、ブロックに User オブジェクトを保持させたくない (そして、ブロックが解放されないようにする) ためです。
したがって、User dealloc メソッドは次のようになります。
- (void)dealloc
{
[[AppClient sharedClient] cancelAllCommandsForSender:self];
[super dealloc];
}
しかし、deallocメソッドで操作をキャンセルしているのに、ユーザーがdeallocを取得した後EXC_BAD_ACCESS
に成功ブロックが呼び出されることがあり、ラインに入るweakSelf.picture = downloadedImage
.
なぜそれが起こっているのですか?操作がキャンセルされた場合でも、接続を終了しようとする可能性はありますか?
ブロックでweakSelfではなくselfのみを使用する場合、ブロックはユーザーを保持するため、これは発生しないことを私は知っています。しかし、私はこの動作を望んでいません。フェッチ操作が存在する場合でも、解放されるとすぐにユーザーが dealloc を取得することを望んでいます。
更新: 操作状態がFinished = YESであることに気付きました。私が使用しているライブラリでは、操作が終了したときに成功ブロックをすぐに実行するのではなく、成功ブロックをメイン キューにディスパッチ_非同期しているようです。
1. ユーザーが画像をフェッチ -> 操作が作成される2. 操作が終了 -> 成功ブロックをディスパッチ_async
(まだ実行されていない)
3. 成功ブロックが実行される前に、ユーザーの割り当て解除 -> すべての操作をキャンセル(ただし、isFinished 状態であるため、step1 からの操作ではありません)
4. これで、成功ブロックが実行されます -> ユーザーを参照しようとすると、EXC_BAD_ACCESS が返されます。
これを解決する方法はまだわかりません..