2012-02-01 14 views
9

キューを使用してメインスレッドのUIを更新することに関連する質問が1つあります。dispatch_get_main_queue()のUIを更新する

UITableViewを作成して、UIImageViewを使用してUILabelを表示するものとします。 UIImageのは、使用して.. prepareCellforに非同期的にロードされる。

dispatch_async(t_queue, ^{ 
    //load image 
    //dispatch_async(dispatch_get_main_queue(),^{ 
    cell.imageView = image; 
    } 
}); 

しかし、ブロックは画像​​をフェッチしている間ユーザが1つのセル(又はナビゲーション・ビュー・コントローラに戻るボタン)そのセルのDetailViewControllerデ負荷(押圧

またはアプリに戻ります)。

私の質問は、ブロックがメインスレッドを起動してセルのimageViewを更新するとどうなりますか?ウィンドウの上にロードされていない、あるいはそれがこれは良い質問です...

おかげ

答えて

14

をアンロードされていることができますのUIViewを更新しようとしています。 ARCを使用した場合の答えは、ブロック自体がオブジェクトを保持しているため、後でそのオブジェクトが保持されるということです。これはそれらの微妙な記憶の一つです。このセルが来るUITableViewが割り当て解除され、すべてのセルを解放すると、このセルは保持され(オフスクリーンでも)、cell.imageView = image;の割り当てが完了してから解放されます。

私は制御された実験の大ファンであり、これをテストするために出発しましたが、UITableViewには多くの可動部分があります。だから私は、次のように簡単なNSObjectサブクラスを使用して、非常に簡単な実験を作成しました:

@implementation SayHello 
-(void)sayHello{ 
    NSLog(@"Hello"); 
} 
-(void)dealloc{ 
    NSLog(@"SayHello dead"); 
} 
@end 

明らかに、このクラスは、ブロック(sayHello)にコールすると、割り当て解除するときNSLogが生成されます私に機能を与えることを目的としています。

私はこのような私のテストを実行しました:

SayHello *hello = [[SayHello alloc] init]; 
dispatch_async(dispatch_get_global_queue(0, 0), ^{ 
    double delayInSeconds = 30.0; 
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
     [hello sayHello]; 
    }); 
}); 

30秒(実際には、それが保持されなかった場合など)は「hello」オブジェクトの割り当てを解除するためにも、最も怠惰な実行ループの時間を与えます。しかし、30秒間はコンソールが黙っています。 30秒が経過すると、すぐに「SayHello dead」というメッセージが表示されます。

これはどのように「つかまえ」ですか?まあ、ブロック/ ARCがこれをやっていることに気付かないのなら、明らかに消えたはずのものを守ることができます。しかし、あなたの例であるUITableViewCellもあります。あなたのセルが一度表示され、ネットワーク経由でイメージを要求したが、ブロックがイメージを待っている間にセルが再利用されている場合はどうなりますか?今、その画像を設定しようとしているそのセルを参照する2番目のブロックがあります。さて、あなたは敗者がどの画像が表示されるかを決めるレースをしました。

関連する問題