簡體   English   中英

在dispatch_get_main_queue()上更新UI

[英]Update UI on 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;
   }
 });

但是當塊正在獲取圖像時,用戶按下一個單元格(或導航視圖控制器上的后退按鈕),為該單元格加載de DetailViewController(或在應用程序中返回)。

我的問題是:當塊啟動主線程以更新單元格的imageView時會發生什么? 它試圖更新未加載到窗口上的UIView,甚至可以卸載它...

謝謝

這是一個很好的問題。 使用ARC時的答案主要是塊本身保留了對象,因此它將在以后使用。 這是那些微妙的記憶陷阱之一。 如果取消分配此單元格的UITableView並釋放其所有單元格,則將保留此單元格(雖然在屏幕外),並且將分配cell.imageView = image; 完成后,它將被釋放。

我是受控實驗的忠實粉絲,並開始測試這個,但UITableView有許多移動部件(沒有雙關語意)。 所以我創建了一個非常簡單的實驗,使用一個簡單的NSObject子類,如下所示:

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

顯然,這個類旨在給我一個函數來調用一個塊( sayHello )並在NSLog分配時生成一個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秒甚至給出了最懶惰的runloop時間來釋放“hello”對象(事實上,如果沒有保留它)。 但對於那些30秒,控制台是沉默的。 在30秒過期后,我立即得到“Hello”,然后是“SayHello dead”消息。

那么這是一個“陷阱”怎么樣? 嗯,很明顯,如果你沒有意識到Blocks / ARC正在這樣做,它最終可能會保留你認為應該消失的東西。 還有你的UITableViewCell示例; 如果您的單元格顯示一次並通過網絡向圖像發送請求怎么辦?但是當塊正在等待圖像時,單元格會被重用? 現在有第二個塊參考該單元試圖設置其圖像。 好吧,現在你有一場比賽,失敗者將決定顯示什么圖像。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM