2014-02-15 184 views
0

我幾乎已經完成編碼我的應用程序,但我仍然有我不能數週解決的一個問題...我瀏覽這個網站,並就同一問題的其他網站,但我不能找不到解決問題的方法。 我有一個表格視圖與單元格(如Instagram)從服務器下載的圖像。我的問題是當我滾動表格視圖時,它不光滑,並且閃爍。細胞的tableview不滾動順利

爲了構建表視圖,i執行以下操作:

-the頭的觀點和將細胞子類。 - 我下載了所有的異步圖像,然後在我的應用程序的tmp文件夾中緩存它們(大約25Ko)。 - 下載的每個圖像都與應該放置的UIImageView具有相同的框架。 - 我試圖以png和jpeg格式保存圖像,但問題依然存在。

我做了另一個試驗,而不是把下載的圖像在細胞內哪裏,我把圖像我的應用程序內(以任意比例)。在這種情況下,表格視圖平滑滾動。

所以我懷疑可能問題是我緩存圖像並從緩存中獲取它們的方式。但即使在這種情況下,我試着用緩存和NSCache一個臨時文件夾中的圖片,但沒有結果......

這裏是我的代碼:

-(void)CacheTheImageDownloaded: (NSData *)TheImageData : (NSString*)PathOfImage{ 

    NSFileHandle *fout; 
    [[NSFileManager defaultManager] createFileAtPath:PathOfImage contents:Nil attributes:Nil]; 
    fout = [NSFileHandle fileHandleForWritingAtPath:PathOfImage]; 
    [fout writeData:TheImageData ]; 
    [fout closeFile]; 

} 


-(UIImage*)GetTheImageFromTemporaryDirectory:(NSString*)ImagePath{ 
    UIImage *theCachedImage; 
    theCachedImage = [UIImage imageWithContentsOfFile:ImagePath]; 
    return theCachedImage; 
} 


-(void)GetImageForTheViewedCell: (NSString*) ImageName : (NSString*)TheImageURL : (NSInteger)therow : (UIImageView*)MyImageView { 

    NSString *TheKey = [NSString stringWithFormat:@"%ld", (long)therow]; 
    NSString *tmpDir = NSTemporaryDirectory(); 
    NSString *ImageDownloadedTmpDir; 
    ImageDownloadedTmpDir = [tmpDir stringByAppendingPathComponent:@"TMPImagesDownloaded"]; 

    NSMutableString *TheImagePath = [NSMutableString stringWithString:ImageDownloadedTmpDir]; 
    [TheImagePath appendString:@"/"]; 
    [TheImagePath appendString:ImageName ]; 

if ([self VerifyIfImageIsAlreadyCached:TheImagePath]){ 
    MyImageView.image = [self GetTheImageFromTemporaryDirectory:TheImagePath]; 
} 
else{ 
    NSBlockOperation *loadImageIntoCellOp = [[NSBlockOperation alloc] init]; 
    [loadImageIntoCellOp addExecutionBlock:^(void){ 
     dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{ 
      NSURL *theURL = [NSURL URLWithString:TheImageURL]; 
      NSData *data1 = [NSData dataWithContentsOfURL:theURL ]; 
      NSData *data = UIImagePNGRepresentation([UIImage imageWithData:data1]); 
      dispatch_sync(dispatch_get_main_queue(), ^{ 
       MyImageView.image = [UIImage imageWithData:data]; 
       NSBlockOperation *ongoingDownloadOperation =  [self.TheImageDownloadOperations objectForKey:TheKey]; 
       if (ongoingDownloadOperation) { 
        [self.TheImageDownloadOperations removeObjectForKey:TheKey]; 
       } 
       [self CacheTheImageDownloaded:data :TheImagePath]; 
      }); 
     }); 
    }]; 

    if (TheKey) { 
     [self.TheImageDownloadOperations setObject:loadImageIntoCellOp forKey:TheKey]; 
    } 

    if (loadImageIntoCellOp) { 
     [self.imageLoadingOperationQueue addOperation:loadImageIntoCellOp]; 
    } 

} 


} 

我在Xcode的5.02合作。

感謝您的建議!

編輯

這裏是我的代碼的cellForRowAtIndexPath:

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


static NSString *cellIdentifier = @"myCustomCell"; 
MyCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier]; 
if (cell == nil){ 
    cell = [[MyCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier]; 
} 
[cell.contentView.subviews makeObjectsPerformSelector:@selector(removeFromSuperview)]; 

NSInteger row = indexPath.row; 
cell.tag = row ; 

//The Profile picture 
NSString *theurl = self.myProfilePics[row]; 
NSString *TheImageName = self.TheImageNames[row]; 
[self GetImageForTheViewedCell:TheImageName:theurl:row: cell.ProfilePicView]; //getting image from the cache or downloaded async 
[cell.TheProfilePicButton setBackgroundImage:cell.ProfilePicView.image forState:UIControlStateNormal]; 
[cell.contentView addSubview: cell.TheProfilePicButton]; 

//Username: 
NSString *myusername = self.Usernames[row]; 
[cell.UsernameButton setTitle: myusername forState:UIControlStateNormal]; 
[cell.contentView addSubview:cell.UsernameButton]; 

//date 
NSString *mydate = self.Dates[row]; 
[cell.DateLabel setText: mydate]; 
[cell.contentView addSubview: cell.DateLabel]; 

return cell; 

} 
+0

你可以嘗試把這條線''main_queue'? '[self CacheTheImageDownloaded:data:TheImagePath];' – jbouaziz

+0

是的,我會嘗試。但由於該方法每個單元只被調用一次,當我多次上下滾動表格視圖時,問題應該消失。你不覺得嗎? – user3170134

+0

我剛剛嘗試過,並且在從緩存中獲取圖像時也做了同樣的事情...問題仍然存在...:/ – user3170134

回答

0

你說, '我試圖將圖像保存爲PNG和JPEG格式'。我想,你只是「保存到緩存」的圖像。你在你的tableview中使用UIImagePNGRepresentation

的UITableView打球時加載許多圖像非常低的表現,即使你實現「延遲加載」。

所以,我的答案是你應該使用UIImageJPEGRepresentation來代替UIImagePNGRepresentation

編輯

如何使用UIGraphicsGetImageFromCurrentImageContext

UIImage *image = [UIImage imageWithContentsOfFile:filePath]; 
CGSize imageSize = image.size; 
UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 
[image drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)]; 
image = UIGraphicsGetImageFromCurrentImageContext(); 
UIGraphicsEndImageContext(); 
UIImageView *imageView = [[UIImageView alloc] initWithImage:image]; 

還有一點,NSCache如何提高性能。這裏是一個樣本

@inteface YourTableViewController() 
@property (nonatomic) NSCache *cache; 
@end 

@implemetation YourTableViewController 

. 
. 
. 

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    NSString *CellIdentifier = @"Cell"; 
    YourCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier]; 

    if (cell == nil) 
    { 
     cell = [[YourCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier]; 
     cell.yourImageView.frame = CGRectMake((self.frame.size.width - self.rowHeight)*0.5f, 0, self.rowHeight, self.rowHeight); 
    } 
    [cell.imageView setImage:nil]; 
    dispatch_queue_t globalQueue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0); 
    dispatch_queue_t mainQueue = dispatch_get_main_queue(); 
    dispatch_async(globalQueue, ^(){ 

     UIImage *image = [self.cache objectForKey:filePath]; 
     if (image == nil) { 
      image = [UIImage imageWithContentsOfFile:filePath]; 
      CGSize imageSize = image.size; 
      UIGraphicsBeginImageContextWithOptions(imageSize, NO, 0); 
      [image drawInRect:CGRectMake(0, 0, imageSize.width, imageSize.height)]; 
      image = UIGraphicsGetImageFromCurrentImageContext(); 
      UIGraphicsEndImageContext(); 
      [self.cache setObject:image forKey:filePath]; 
     } 

     dispatch_async(mainQueue, ^(){ 
      if ([[tableView indexPathsForVisibleRows] containsObject:indexPath]) { 
       YourCell *cell = (YourCell *)[tableView cellForRowAtIndexPath:indexPath]; 
       if(image) { 
        [cell.yourImageView setImage:image]; 
       } 
      } 
     }); 
    }); 
    return cell; 
} 

. 
. 
. 

@end 
+0

下載的所有圖像都是用戶在應用中拍攝的圖像,因此我試圖在將它們上傳到服務器之前將它們保存爲jpeg和png。我更喜歡UIImageJPEGRepresentation,因爲我可以控制質量,並減少每個圖像的重量。 – user3170134

+0

你可以在UIViewController中顯示-cellForRowAtIndexPath:? – ryutamaki

+0

我只是把它!看到我的編輯 – user3170134