2013-12-16 127 views
1

我們想要下載圖像和數據異步到我們的tableview,我們想緩存它不要再下載它。我們找到了一個緩存代碼。這裏是我們的代碼。它異步工作,但當我們滾動表視圖時,圖像消失並返回(我們暫時看不到圖像)。有時候錯誤的圖像來錯誤的單元格。可能是什麼原因,我們如何解決它?xcode異步tableview加載圖像移動listview圖像去了

NSURL *imageURL = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@",[userInfo[0] serverUrl],[estateList[indexPath.row] imgUrl]]]; 

    NSString *key = [imageURL absoluteString]; 
    NSData *data = [FTWCache objectForKey:key]; 
    if (data) { 
     UIImage *image = [UIImage imageWithData:data]; 
     cell.imageView.image = image; 
    } else { 
     cell.imageView.image = [UIImage imageNamed:@"yukleniyor"]; 
     dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_HIGH, 0ul); 
     dispatch_async(queue, ^{ 
      NSData *data = [NSData dataWithContentsOfURL:imageURL]; 
      [FTWCache setObject:data forKey:key]; 
      UIImage *image = [UIImage imageWithData:data]; 
      dispatch_async(dispatch_get_main_queue(), ^{ 
       cell.imageView.image = image; 
      }); 
     }); 
    } 

這裏是代碼,我們發現緩存

標題是這樣的

#import <Foundation/Foundation.h> 

@interface FTWCache : NSObject 

+ (void) resetCache; 

+ (void) setObject:(NSData*)data forKey:(NSString*)key; 
+ (id) objectForKey:(NSString*)key; 

@end 

而且.m文件是這樣

#import "FTWCache.h" 

static NSTimeInterval cacheTime = (double)604800; 

@implementation FTWCache 

+ (void) resetCache { 
    [[NSFileManager defaultManager] removeItemAtPath:[FTWCache cacheDirectory] error:nil]; 
} 

+ (NSString*) cacheDirectory { 
    NSArray* paths = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES); 
    NSString *cacheDirectory = [paths objectAtIndex:0]; 
    cacheDirectory = [cacheDirectory stringByAppendingPathComponent:@"FTWCaches"]; 
    return cacheDirectory; 
} 

+ (NSData*) objectForKey:(NSString*)key { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSString *filename = [self.cacheDirectory stringByAppendingPathComponent:key]; 

    if ([fileManager fileExistsAtPath:filename]) 
    { 
     NSDate *modificationDate = [[fileManager attributesOfItemAtPath:filename error:nil] objectForKey:NSFileModificationDate]; 
     if ([modificationDate timeIntervalSinceNow] > cacheTime) { 
      [fileManager removeItemAtPath:filename error:nil]; 
     } else { 
      NSData *data = [NSData dataWithContentsOfFile:filename]; 
      return data; 
     } 
    } 
    return nil; 
} 

+ (void) setObject:(NSData*)data forKey:(NSString*)key { 
    NSFileManager *fileManager = [NSFileManager defaultManager]; 
    NSString *filename = [self.cacheDirectory stringByAppendingPathComponent:key]; 

    BOOL isDir = YES; 
    if (![fileManager fileExistsAtPath:self.cacheDirectory isDirectory:&isDir]) { 
     [fileManager createDirectoryAtPath:self.cacheDirectory withIntermediateDirectories:NO attributes:nil error:nil]; 
    } 

    NSError *error; 
    @try { 
     [data writeToFile:filename options:NSDataWritingAtomic error:&error]; 
    } 
    @catch (NSException * e) { 
     //TODO: error handling maybe 
    } 
} 


@end 
+0

與TableView中短代碼部分能否請您解釋一下這個具有與'Xcode的IDE'辦? – Popeye

+0

我沒有正確地讀完代碼,並且我沒有緩存的答案,但也許是對圖像的一種想法:出現在錯誤行上的圖像可能是來自tableView出隊過程的結果。當一行退出tableView的可見部分時,它不會被刪除,它會被出列。當你滾動一行時,它將被重新用於另一行。當在一行中同步呈現圖像時,這可能意味着先前下載的圖像仍然在上一次顯示的這一行中(即,進一步向上),並且將在下載第二圖像時替換它自身。 – Sti

+0

(如果是這樣的話,這個特定問題的一個解決方案是在調用獲取異步映像的方法之前,特別清空「cellForRowAtIndexPath」中的'imageView'(或'setHidden:YES') setHidden:NO')) – Sti

回答

0

對不起,我以前的答案。 我會試着解釋一下這個問題: 我們有TableView顯示器保留區域的行數和行數。因此,具有異步加載的圖像無法加載到其單元格中(因爲它是從內存下載時插入的)。

解決方案非常簡單,您必須爲每個ImageView分配鍵和與該表的單元格關聯的此鍵。

我使用代碼從這個混帳解決此問題(https://gist.github.com/khanlou/4998479

有上有兩個文件

UIImageView+Network.h 
UIImageView+Network.m 

您必須包括他們在您的項目,或者創建自己的類並粘貼到它。

本課程使用來自(https://github.com/FTW/FTWCache/tree/master/FTWCache)的FTW/FTWCache。所以你也必須添加到你的項目中。

之後,你必須在其中將使用異步圖像加載和緩存文件導入

#import "UIImageView+Network.h" 

而且使用

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

    MyTableCell *cell = (MyTableCell *)[tableView dequeueReusableCellWithIdentifier:simpleTableIdentifier]; 
    if (cell == nil){ 
     NSArray *nib = [[NSBundle mainBundle] loadNibNamed:@"MyTableCell" owner:self options:nil]; 
     cell = [nib objectAtIndex:0]; 
    } 
    // construction to call method 
    // [cell.imageView loadImageFromURL:(NSURL*)url placeholderImage:(UIImage*)placeholder cachingKey:(NSString*)key ]; 

    [cell.thumbnailImageView loadImageFromURL:(NSURL*)url placeholderImage:[UIImage imageNamed:@"no_foto.gif"] cachingKey:(NSString*)[NSString stringWithFormat:@"%d",indexPath.row]]; 

    return cell; 
} 
+1

請考慮刪除您之前僅提供了一個鏈接的downvoted答案。 –

+0

感謝您的關注和幫助!) – Nikita

+0

不客氣:) –