0

UITableView のセルに画像を非同期的にロードしています。コードは次のようになります。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

// after getting the cell..

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        NSString *imageUrl = [someMethodToGetImageUrl];
        NSData *imageData = [[NSData alloc] initWithContentsOfURL:[NSURL imageUrl]];
        dispatch_async(dispatch_get_main_queue(), ^{
            cell.imageView.image = [UIImage imageWithData:imageData];
            [tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];
        });
    });

}

私の質問は、ディスパッチを開始した後、スレッドがセルの画像の設定を完了する前に、この tableView の割り当てが解除された場合 (たとえば、navigationController スタックからポップされた場合) にどうなるかに関するものです。セルも割り当て解除され、そのセルに何かをしようとするとクラッシュが発生しますよね?

上記のコードでクラッシュしていました。この tableView にセグエインしてすぐに戻ると、次の行でクラッシュが発生します。

[tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];

それを次のように変更すると:

[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationNone];

クラッシュはなくなりますが、これは私には意味がありません。なぜこれが事実なのか、誰かが私に説明できますか?ありがとう。

4

1 に答える 1

2

元のスコープを超えてブロックを保持する可能性のあるルーチンは、ブロックをコピーする必要があります。 dispatch_async()します。

ブロックがコピーされると、参照するオブジェクト ポインター変数が保持されます。selfブロックがインスタンス変数の形式で暗黙的にアクセスする場合、保持されますself。それ自体が解放されるまで、これらの参照を保持します。

あなたの例でcellは、 、imageDataindexPath、およびtableViewは、ブロックが終了するまですべて保持されます。

于 2012-04-18T23:07:56.273 に答える