6

NSOperationsWeb API へのサービス呼び出しを管理するために使用するアプリがあります (呼び出しは、Jon Wight の touchcode の CURLOperation に基づいています)。

マップ ビューの中心が大幅に変化したときに、マップの位置をダウンロードする特定の呼び出しがあります。これらはすぐにスタックする可能性があるため、マップを移動すると、古い操作を積極的にキャンセルしようとします. 4.0でうまく機能します。

ただし、3.1 では、特定のケースでは、オペレーション キューがキャンセルされた (および解放された) オペレーションを保持し、キューにあるはずの場所に到達したときにクラッシュを引き起こすようです。

これがイラストです。

キュー内の比較的重いサービス コールから始めます。

  1. MyLongRunningOp 0x1

ユーザーがマップに移動します。キューは次のようになります。

  1. MyLongRunningOp 0x1
  2. MyMapOp 0x2

マップを移動すると、MyMapOp 0x2 がキャンセルされ、MyMapOp 0x3 が追加されます。

  1. MyLongRunningOp 0x1
  2. MyMapOp 0x3

MyMapOp 0x2キューから削除されたため、リリースされました。これMyLongRunningOp 0x1で終了。isFinished キーを on に設定するための KVO コールバックでMyLongRunningOpは、操作キューが通知を処理し、MyMapOp 0x2いくつかの に追加しようとしていることがわかりますNSArray。当然、NSZombies有効にすると、

[MyMapOp retain]: message sent to deallocated instance 0x2

NSOperationQueueキャンセル/解放された操作へのポインタに何らかの形でぶら下がっており、前の操作が終了した後にそれをアクティブにしようとしているようです。

4.0 でこの動作を再現できなかったので、3.1 のバグだと思います。

私が知る限り、唯一の回避策は操作をキャンセルしないことです。これにより、ネットワークが不安定になったときに次善のエクスペリエンスが得られます。

他の誰かがこれを経験しましたか?何か案は?

4

1 に答える 1

1

NSOperations で KVO を使用して同様の問題が発生しました。

あなたの説明を読んだだけで、私の最初の本能は、操作キューのルールを確認することです. キューに渡すと、キューが所有権を引き継ぐ必要があるため、手動で解放しないでください。(あなたがそうであるかどうかはわかりません)。

私の個人的な経験から、おそらくそれが役立つかどうか:

1) op をキャンセルするときは、そこから KVO オブザーバーを削除します。どちらかの側が削除されても、KVO のリンクが解除されないことがありました。

2) KVO コールバックは NSOperation と同じスレッドで実行されることに注意してください。そのため、操作を開始してから KVO コールバックまでの間に、オブジェクトが範囲外になる可能性があります。

コードを投稿していただければ、さらにお役に立てるかもしれません。上記がお役に立てば幸いです。

于 2011-05-10T15:47:23.847 に答える