表视图中的单元格滚动不顺畅



我几乎已经完成了应用程序的编码,但我仍然有一个问题,我几个星期都无法解决。。。我浏览了这个网站和其他网站,但我找不到解决问题的方法。我有一个带有从服务器下载的图片的单元格(如Instagram)的表格视图。我的问题是,当我滚动表格视图时,它不平滑,而且会闪烁。

为了构建表视图,我执行以下操作:

-头视图和单元格被划分为子类。-我异步下载所有的图像,然后将它们缓存在我的应用程序的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;
}

你说‘我试图用png和jpeg格式保存图像’。我想,你只是"保存以缓存"图像。并且在表视图中使用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

最新更新