2014-02-15 137 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