1

バックグラウンドでいくつかの作業を行い、完了ハンドラーを呼び出すライブラリを使用しています。すべて本当に標準です。

[[LastFm sharedInstance] getInfoForArtist:@"Pink Floyd" successHandler:^(NSDictionary *result) {
    // Do stuff...
} failureHandler:nil];

私は実際にこれをテーブルビュー内で使用しています。すべてのセル(サブクラス)で、アーティストに関する情報を取得して表示します。これも問題です。セルを画面外に移動して別のアーティストに再利用する場合でも、前のアーティストのsuccessHandlerを実行できるため、ラベルと画像が連続して複数回変更されます。

私の考えは、NSOperationQueueを作成し、その中にgetInfoForArtist呼び出しを追加して、キャンセルできることを確認することでした。

NSBlockOperation *operation = [[NSBlockOperation alloc] init];
__weak NSBlockOperation *weakOperation = operation;

[operation addExecutionBlock:^{
    [[LastFm sharedInstance] getInfoForArtist:mediaItem.artist successHandler:^(NSDictionary *result) {
        if (weakOperation.isCancelled) {
            return;
        }
        // Do stuff...
    } failureHandler:nil];
}];

[self.queue addOperation:operation];

問題はweakOperation、successHandler内では常にnullであるということです。__blockの代わりに変更すると__weakweakOperationは正しいインスタンスですが、そのisCancelled状態は常にNOです。

[self.queue cancelAllOperations];セルが画面から移動した正しい時刻に電話をかけています。

だから私の質問は、セルが別のアーティストに再利用された後にsuccessHandlerが実行されないようにするにはどうすればよいですか?

4

1 に答える 1

2

問題は、非同期APIを呼び出していることです。操作の存続期間はへの呼び出しgetInfoForArtist:successHandler:であり、おそらくすぐに戻ります。非同期コールバックが実行されるまでに、操作は破棄されています。そのため、コールバックブロック内の参照はnilです。

successHandlerが実行されるまでに、操作をキャンセルしても意味がありません。ネットワークリソースを節約することはなく、ルックアップの結果をローカルに保存することもできます。UIの問題は、セル(または、それらを再利用する場合はそのサブビュー)を直接参照してはならないことです。NSDictionary行のいずれかにキーが設定されたローカルNSIndexPathまたはアーティストIDに結果を保存することを検討してください。次に、でcellForRowAtIndexPath:、LastFM呼び出しを行う前に、まずその辞書を確認します。successHandlerコールバックでは、tableViewを反復visibleCells処理して、ディクショナリからデータをロードしようとすることができます。

于 2012-10-31T21:52:24.783 に答える