2014-11-06 57 views
0

我已經創建了一個UITableView,它可以從URL請求中填充每個單元格。我使用'dispatch_queue'來防止UItableView凍結。由於某種原因,當我滾動UITableView時,圖像閃爍並消失,並填充錯誤的單元格,直到修復它們自己。這是我的代碼。我正在使用restkit提供飼料UITableView中的圖像在滾動時不斷重新加載和錯誤的圖像閃爍

customCell.customCellTextLabel.text = [NSString stringWithFormat:@"%@",feedO.title]; 

    NSString *string = [NSString stringWithFormat:@"%@",feedO.body]; 

    NSURL *urlString; 

     NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; 
     NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])]; 
     for (NSTextCheckingResult *match in matches) { 
      if ([match resultType] == NSTextCheckingTypeLink) { 
       urlString = [match URL]; 
       NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title); 
      } 
     } 

     dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil); 
     dispatch_async(imageQueue, ^{ 

      NSData *data = [[NSData alloc] initWithContentsOfURL:urlString]; 

      dispatch_async(dispatch_get_main_queue(), ^{ 

       customCell.customCellImageView.image = [UIImage imageWithData: data]; 
      }); 
     }); 


    return customCell; 
+0

當您滾動您的每一次細胞會重新下載圖像。我更喜歡使用(https://github.com/rs/SDWebImage)。這是很好的庫,下載圖像異步,它也保持緩存。因爲根據你的代碼。如果你的單元格索引爲0to5下載圖像。當你再次回到索引0to5時,你的圖像將再次下載。 – 2014-11-06 09:36:55

回答

0

你應該考慮使用這個庫SDWebImage,在這裏可以得到這種問題https://github.com/rs/SDWebImage。它可以輕鬆處理遠程圖像的異步下載和緩存。

的simpliest安裝使用的CocoaPods

的CocoaPods(http://cocoapods.org)做的是,Objective-C的功能,可自動並簡化在項目中使用第三方庫的過程中依賴管理。 有關更多詳細信息,請參閱入門部分。

使用您Podfile

platform :ios, '6.1' 
pod 'SDWebImage', '~>3.6' 

安裝用於SDWebImage的依賴後,只需簡單地使用在您的視圖控制器下面幾行:

#import <SDWebImage/UIImageView+WebCache.h> 

... 

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *MyIdentifier = @"MyIdentifier"; 

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:MyIdentifier]; 

    if (cell == nil) 
    { 
     cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault 
             reuseIdentifier:MyIdentifier] autorelease]; 
    } 

    // Here we use the new provided setImageWithURL: method to load the web image 
    [cell.imageView setImageWithURL:[NSURL URLWithString:@"http://www.domain.com/path/to/image.jpg"] 
        placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; 

    cell.textLabel.text = @"My Text"; 
    return cell; 
} 
+0

我以前試過這個,但是我沒有發現它清楚SDWebImage哪些文件需要添加到我的項目中?我只需將名爲'SDWebImage'的文件夾添加到我的項目中? – burrGGG 2014-11-06 10:54:24

+0

最簡單的方法是在項目中使用Pods(http://cocoapods.org)來管理第三方庫的依賴關係。只需在您的PodFile中添加一個依賴到完整的SDWebImage項目,然後使用我在我的回答 – cdescours 2014-11-06 10:59:42

+0

中提供的代碼非常感謝您的幫助,我使用了可可豆莢,我用它來爲我的項目安裝'RestKit'但不知道如何安裝SDWebImage – burrGGG 2014-11-06 11:03:23

0

您的代碼缺少一行,即我添加的。

customCell.customCellImageView.image = nil;

customCell.customCellTextLabel.text = [NSString stringWithFormat:@"%@",feedO.title]; 

NSString *string = [NSString stringWithFormat:@"%@",feedO.body]; 

NSURL *urlString; 
customCell.customCellImageView.image =nil; 

    NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; 
    NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])]; 
    for (NSTextCheckingResult *match in matches) { 
     if ([match resultType] == NSTextCheckingTypeLink) { 
      urlString = [match URL]; 
      NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title); 
     } 
    } 

    dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil); 
    dispatch_async(imageQueue, ^{ 

     NSData *data = [[NSData alloc] initWithContentsOfURL:urlString]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      customCell.customCellImageView.image = [UIImage imageWithData: data]; 
     }); 
    }); 


return customCell; 
+1

由於這也是一個計時問題,因此無法解決問題。 – mbogh 2014-11-06 09:31:47

0

原因是UITableView正在重新使用所創建的單元格。 所以首先它創建讓你的CustomCell類10說。

小區0
小區1
...
細胞9

通過創建這些10個細胞,將引發10異步調用來獲取圖像。

塊0 - >細胞0
塊1 - >小區1
...
塊9 - >單元9

這將正常工作,如果你不滾動,直到所有10個下載有完了。

但是一旦開始滾動,UITableView將開始重新使用創建的單元格並啓動新的下載。

所以首先它可能複用小區0和創建塊10 - >小區0

如果0號塊沒有完成時,小區0中入選了重用,你現在有兩個街區希望把自己的形象上同一個單元格。 領先於以下兩種情況:

  1. 塊0完,然後再阻斷10只
  2. 10座完成第一,那麼在塊0

這是什麼原因造成的 「閃爍」。

然後想象經過的小區1000滾動秒內:)

解決方案

你需要能夠取消排隊塊的細胞被重用。

我會使用例如SDWebImageFastImageCache

+0

哦,好吧,有沒有辦法阻止我?此外,它似乎是重新加載所有圖像時,我滾動回頂部等..? – burrGGG 2014-11-06 09:35:47

+0

太快點擊按鈕,更新了建議。 – mbogh 2014-11-06 09:36:42

0

你是怎麼說的。你在另一個線程中捕捉圖像,以防止凍結。在tableView中,單元格被重用,並且在一個後臺線程中捕獲新照片,在主線程中返回具有上一張照片的單元格。 這裏在代碼中,我修復它並更好地解釋:

customCell.customCellTextLabel.text = [NSString stringWithFormat:@「%@」,feedO.title];

NSString *string = [NSString stringWithFormat:@"%@",feedO.body]; 

NSURL *urlString; 

    NSDataDetector *linkDetector = [NSDataDetector dataDetectorWithTypes:NSTextCheckingTypeLink error:nil]; 
    NSArray *matches = [linkDetector matchesInString:string options:0 range:NSMakeRange(0, [string length])]; 
    for (NSTextCheckingResult *match in matches) { 
     if ([match resultType] == NSTextCheckingTypeLink) { 
      urlString = [match URL]; 
      NSLog(@"found Body URL: %@ and title %@", urlString,feedO.title); 
     } 
    } 
    // Here you need, at least quit the previous imagen, is better if you implement 
    // and activity indicator (here start), and also you should implement some imagen cache. 
    customCell.customCellImageView.image = nil; 


    // Apart from here, go to another thread. 

    dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil); 
    dispatch_async(imageQueue, ^{ 

     // this operation is slowly that return a cell, this happens after [1] 
     NSData *data = [[NSData alloc] initWithContentsOfURL:urlString]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 

     //If you implement and activity indicator stop here. 
      customCell.customCellImageView.image = [UIImage imageWithData: data]; 
     }); 
    }); 

// [1] the cell is returned before the image is ready. 
return customCell; 
0

上面的回答是正確的。但不需要爲單元格下載圖像。您可以在表格加載發生之前在viewWillAppear或ViewDidLoad中下載圖像,以符合您的要求。

0

當您每次圖像再次下載時滾動表格。爲了防止這種情況,我更喜歡你從緩存中獲取圖像,並直接在你的圖像視圖中設置。根據你的代碼。如果您從0索引滾動到10,則單元格將下載全部10個單元格的圖像。之後如果您再次滾動10到索引0。那麼圖像會再次下載。

您可以使用(https://github.com/rs/SDWebImage)下載圖像異步。它非常簡單快捷。

我喜歡這個庫,因爲它會處理您的緩存。只需在下面輸入代碼

#import "UIImageView+WebCache.h" 

// in cellForRowAtIndexPath. 
[customCell.customCellImageView sd_setImageWithURL: [NSURL URLWithString:urlString]]; 

刪除下面的代碼。

dispatch_queue_t imageQueue = dispatch_queue_create("imageDownloader",nil); 
    dispatch_async(imageQueue, ^{ 

     NSData *data = [[NSData alloc] initWithContentsOfURL:urlString]; 

     dispatch_async(dispatch_get_main_queue(), ^{ 

      customCell.customCellImageView.image = [UIImage imageWithData: data]; 
     }); 
    }); 

也許這會幫助你。

+0

我以前試過這個,但是我沒有發現它清楚SDWebImage中哪些文件需要添加到我的項目中?我只需將名爲'SDWebImage'的文件夾添加到我的項目中? – burrGGG 2014-11-06 10:53:44

+0

@burrGGG yes在您的project.add中添加文件夾名稱「SDWebImage」「ImageIO.framework」,並將其他鏈接器標誌設置爲「-ObjC」和「#import」UIImageView + WebCache.h「'。你就完成了。如果您知道如何安裝,也可以安裝pod文件。 – 2014-11-06 10:58:53

+0

@burrGGG使用'pod'SDWebImage','〜> 3.6''來安裝pod。 – 2014-11-06 11:05:24