亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

為了賬號安全,請及時綁定郵箱和手機立即綁定
已解決430363個問題,去搜搜看,總會有你想問的

使用GCD異步下載UITableView的圖像

使用GCD異步下載UITableView的圖像

iOS
MMTTMM 2019-10-08 14:51:33
我正在使用GCD異步下載uitableview的圖像,但是有一個問題-滾動圖像閃爍并一直更改時。我嘗試將每個單元格的圖像設置為nil,但這并沒有太大幫助??焖傧蛏蠞L動時,所有圖像均不正確。我該怎么辦?這是我的細胞方法:- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{    static NSString *CellIdentifier = @"Cell";    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];    if (self.loader.parsedData[indexPath.row] != nil)    {        cell.imageView.image = nil;        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);            dispatch_async(queue, ^(void) {                NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self.loader.parsedData[indexPath.row] objectForKey:@"imageLR"]]];                UIImage* image = [[UIImage alloc] initWithData:imageData];                dispatch_async(dispatch_get_main_queue(), ^{                    cell.imageView.image = image;                    [cell setNeedsLayout];                     });            });    cell.textLabel.text = [self.loader.parsedData[indexPath.row] objectForKey:@"id"];    }    return cell;}
查看完整描述

3 回答

?
GCT1015

TA貢獻1827條經驗 獲得超4個贊

這里的問題是您的圖像獲取塊正在保存對tableview單元的引用。下載完成后,imageView.image即使您回收了單元格以顯示其他行,它也會設置屬性。


在設置映像之前,您需要下載完成塊來測試映像是否仍與單元格相關。


還需要注意的是,您不會將圖像存儲在單元格中以外的任何位置,因此,每次在屏幕上滾動一行時,您都將再次下載它們。您可能希望將它們緩存在某個位置,并在開始下載之前查找本地緩存的圖像。


編輯:這是使用單元格的tag屬性進行測試的簡單方法:


- (UITableViewCell *)tableView:(UITableView *)tableView 

         cellForRowAtIndexPath:(NSIndexPath *)indexPath

{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];


    cell.tag = indexPath.row;

    NSDictionary *parsedData = self.loader.parsedData[indexPath.row];

    if (parsedData)

    {

        cell.imageView.image = nil;

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

        dispatch_async(queue, ^(void) {


            NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:parsedData[@"imageLR"]];


            UIImage* image = [[UIImage alloc] initWithData:imageData];

            if (image) {

                 dispatch_async(dispatch_get_main_queue(), ^{

                     if (cell.tag == indexPath.row) {

                         cell.imageView.image = image;

                         [cell setNeedsLayout];

                     }

                 });

             }

        });


        cell.textLabel.text = parsedData[@"id"];

    }

    return cell;

}


查看完整回答
反對 回復 2019-10-08
?
ibeautiful

TA貢獻1993條經驗 獲得超6個贊

關鍵是您沒有完全了解單元重用概念。這與異步下載不太吻合。



    ^{

    cell.imageView.image = image;

    [cell setNeedsLayout];

}

在請求完成并且所有數據都已加載時被執行。但是,在創建塊時,單元會獲得其值。


到執行塊時,單元仍指向現有單元之一。但是用戶很有可能繼續滾動。同時,該單元格對象已被重新使用,并且該圖像與“ 舊 ”單元格相關聯,該單元格已被重用,分配和顯示。之后不久,除非用戶進一步滾動,否則將加載并分配并顯示正確的圖像。等等等等。


您應該尋找一種更聰明的方法。有很多花絮。Google用于延遲加載圖片。


查看完整回答
反對 回復 2019-10-08
?
慕俠2389804

TA貢獻1719條經驗 獲得超6個贊

使用索引路徑獲取單元格。如果看不到該單元格nil,則不會有問題。當然,您可能希望在下載數據時緩存數據,以便在已有圖像后立即設置單元格的圖像。


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

{

    static NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];


    if (self.loader.parsedData[indexPath.row] != nil)

    {

        cell.imageView.image = nil;

        dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul);

            dispatch_async(queue, ^(void) {

                //  You may want to cache this explicitly instead of reloading every time.

                NSData *imageData = [NSData dataWithContentsOfURL:[NSURL URLWithString:[self.loader.parsedData[indexPath.row] objectForKey:@"imageLR"]]];

                UIImage* image = [[UIImage alloc] initWithData:imageData];

                dispatch_async(dispatch_get_main_queue(), ^{

                    // Capture the indexPath variable, not the cell variable, and use that

                    UITableViewCell *blockCell = [tableView cellForRowAtIndexPath:indexPath];

                    blockCell.imageView.image = image;

                    [blockCell setNeedsLayout];

                });

            });

        cell.textLabel.text = [self.loader.parsedData[indexPath.row] objectForKey:@"id"];

    }


    return cell;

}


查看完整回答
反對 回復 2019-10-08
  • 3 回答
  • 0 關注
  • 556 瀏覽

添加回答

舉報

0/150
提交
取消
微信客服

購課補貼
聯系客服咨詢優惠詳情

幫助反饋 APP下載

慕課網APP
您的移動學習伙伴

公眾號

掃描二維碼
關注慕課網微信公眾號