簡體   English   中英

iPhone-GCD第一次不起作用

[英]iPhone - GCD doesn't work for the first time

在我的應用程序中,我從URL加載圖像:

-(void)loadImages
{
    ...

    image1 = [UIImage imageWithData:[NSData dataWithContentsOfURL:imgUrl1]];
}

為了避免在下載完成之前阻塞主線程,我使用GCD-viewDidAppear中調用此方法:

dispatch_async( dispatch_get_global_queue(0,0), ^{
            [self loadImages];
        });

但是,當我第一次使用imageView打開view controller時, imageView是空的(即使我等待了很長時間),但是當我再次打開此view controller並且出現圖像后,一切都很好。

我的錯誤在哪里? 抱歉,多線程新手:)

編輯 :我也忘了提一下,當我得到它時,我在tableView使用圖像:

 cell.imageView.image = image1;

iOS中的UIElement應始終通過主線程進行更新。 您可以做的是:-

   __block NSData *data;
    dispatch_queue_t myQueue = dispatch_queue_create("com.appName", NULL);
    dispatch_async(myQueue, ^{
       data = [NSData dataWithContentsOfURL:imgUrl1];
       dispatch_async(dispatch_get_main_queue(), ^(void) {
       cell.imageView.image = [UIImage imageWithData = data];
    });
    });

否則,您可以使用AFNetworking從URL獲取圖像的更好方法。 它更快,更容易。 您只需要編寫一行代碼:-

[cell.imageView setImageWithURL:imgUrl1];

這可能不是您要找的答案,但這不是建議的加載URL的方法。 您應該使用可用的URL加載類,例如NSURLRequest和NSURLConnection。

嘗試這個:

NSURLRequest *imageRequest = [[NSURLRequest alloc] initWithURL:imageURL];
[NSURLConnection sendAsynchronousRequest:imageRequest queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *error) {
    if (!error) {
        UIImage *image = [[UIImage alloc] initWithData:data];
        [imageView setImage:image];
    }
}];

您需要通知視圖該圖像需要重繪。 加:

[imageView setNeedsDisplay];

loadImages方法的末尾。

您在這里遇到許多問題:

  1. 您無法在未運行Runloop的線程上啟動網絡請求。
  2. 您不能從主線程以外的其他線程更新UI。
  3. [NSData dataWithContentsOfURL:imgUrl1]並不是加載外部資源的安全方法,即使在其他線程上(尤其是在主線程上)也是如此。
  4. 每當您分派到另一個線程時,都將面臨表單元已被回收並且不再顯示您認為是的數據的風​​險。 (它仍然是相同的單元格實例,但是現在正在顯示其他行的數據。)

您應該做什么:

  1. 使用主線程上的異步調用啟動網絡操作。 (如果需要,可以使用另一個線程或隊列,但是需要確保它正在運行運行循環。)
  2. 從您的委托消息中,將圖像解碼分派到另一個線程上。
  3. 圖像解碼后,分派回主線程進行更新。
  4. 在實際分配圖像之前,請檢查該單元是否仍在用於您認為的目的。

您可以使用AFNetworking解決前三個問題。 它包裝了委托方法,並讓您僅提供成功和失敗塊。 正如我所描述的,AFNetworking的AFImageRequestOperation特別是在隊列之間反彈代碼。 (它甚至在不同的線程中運行其主要的網絡循環,這不是必需的,但是既然做得很好,為什么不呢?)

您仍然需要驗證單元格的身份。

由於您在TableView中使用它,因此添加[self.tableView reloadData]; 在loadImages方法的末尾。

暫無
暫無

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

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