我的UITableView上有平滑的滚动问题,UITableViewCell包含UIImageView。在StrackOverflow上可以找到类似的问题,但是所提出的解决方案都没有帮助我彻底摆脱滞后。
我的情况很常见:
我遵循了多个优化提示,并设法优化滚动。 不幸的是它仍然不完美。这是我的情景:
最初在开始新的后台线程之前获取图像(步骤1)是没有后台线程的UIImage缓存检查。在这种情况下,如果我们在缓存中有图像,我们会立即分配它,这会在快速滚动期间引入很大的延迟(只要我们立即获取图像,我们就会经常分配图像)。我在下面的例子中对这些行进行了评论。
还有两个问题:
有人建议如何处理这两个问题或如何优化我的方案
请考虑使用Xamarin编写的示例,但我不相信Xamarin是导致问题的原因,只要我对ObjectiveC中编写的应用程序也有同样的问题。
答案 0 :(得分:10)
您是否曾尝试使用保存在TableView
中的一张120x120图片填充Bundle
?这样,您可以检查Image rendering
我建议您创建并使用所有图片的缩略图,而不是将所有图片调整为120x120并将其保存在缓存中。你已经在某种程度上这样做了,但你这样做了几次(每次你滚动或者你的缓存已经满了)。
在我们的上一个项目中,我们有UICollectionView
书籍封面。大多数封面都在400-800kb之间,滚动时的感觉非常糟糕。所以我们为每个图像创建了一个缩略图(缩略图大约40-50kb),并使用缩略图而不是真正的封面。奇迹般有效!我附上了缩略图创建功能
- (BOOL) createThumbnailForImageAtFilePath:(NSString *)sourcePath withName:(NSString *)name {
UIImage* sourceImage = [UIImage imageWithContentsOfFile:sourcePath];
if (!sourceImage) {
//...
return NO;
}
CGSize thumbnailSize = CGSizeMake(128,198);
float imgAspectRatio = sourceImage.size.height / sourceImage.size.width;
float thumbnailAspectRatio = thumbnailSize.height/thumbnailSize.width;
CGSize scaledSize = thumbnailSize;
if(imgAspectRatio >= thumbnailAspectRatio){
//image is higher than thumbnail
scaledSize.width = scaledSize.height * thumbnailSize.width / thumbnailSize.height;
}
else{
//image is broader than thumbnail
scaledSize.height = scaledSize.width * imgAspectRatio;
}
UIGraphicsBeginImageContextWithOptions( scaledSize, NO, 0.0 );
CGRect scaledImageRect = CGRectMake( 0.0, 0.0, scaledSize.width, scaledSize.height );
[sourceImage drawInRect:scaledImageRect];
UIImage* destImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
NSString* thumbnailFilePath = [[self SOMEDIRECTORY] stringByAppendingPathComponent:name];
BOOL success = [UIImageJPEGRepresentation(destImage, 0.9) writeToFile:thumbnailFilePath atomically:NO];
return success;
}
答案 1 :(得分:3)
尝试使用facebook的异步显示库。
https://github.com/facebook/AsyncDisplayKit
非常容易使用..来自他们的指南:http://asyncdisplaykit.org/guide/
_imageNode = [[ASImageNode alloc] init];
_imageNode.backgroundColor = [UIColor lightGrayColor];
_imageNode.image = [UIImage imageNamed:@"hello"];
_imageNode.frame = CGRectMake(10.0f, 10.0f, 40.0f, 40.0f);
[self.view addSubview:_imageNode.view];
这会在后台线程上解码图像。
我不确定在Xamarin上使用iOS库是否容易,但如果它很容易,那么就试一试。
答案 2 :(得分:2)
我是Paul Hegarty的CoreDataTableViewController子类,并在CoreDataTableView中使用我的照片的缩略图。
查看标题为FlickrFetcher and Photomania的第14讲中的示例。您还需要在同一链接下载CoreDataTableViewController。
使用适当的标题创建CoreData实体,并定义所需的任何属性(数据变量)。您需要定义两个“可转换”属性,一个用于照片,另一个用于缩略图。
然后在CoreDataTableView中加载缩略图:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{ NSArray * exceptions = [NSArray arrayWithObjects:@“SCR”,@“DNS”,@“NT”,@“ND”,@“NH”,nil];
static NSString *CellIdentifier = @"resultsDisplayCell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
if (cell == nil) {
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:CellIdentifier];
}
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
MarksFromMeets *athleteMarks = [self.fetchedResultsController objectAtIndexPath:indexPath];
NSString* date = [ITrackHelperMethods dateToAbbreviatedString:athleteMarks.meetDate];
NSMutableString *title = [NSMutableString stringWithFormat:@"%@", athleteMarks.markInEvent];
NSMutableString *subTitle = [NSMutableString stringWithFormat:@"%@ - %@",date, athleteMarks.meetName];
[title replaceOccurrencesOfString:@"(null)"
withString:@""
options:0
range:NSMakeRange(0, [title length])];
// cell.imageView.image = athleteMarks.photoThumbNail; // Don't like image in front of record.
[cell.textLabel setFont:[UIFont
fontWithName:@"Helvetica Neue" size:18]];
[cell.detailTextLabel setFont:[UIFont fontWithName:@"Helvetica Neue" size:16]];
[cell.detailTextLabel setTextColor:[UIColor grayColor]];
// make selected items orange
if ([athleteMarks.eventPR integerValue] != 0
&& (![exceptions containsObject:athleteMarks.markInEvent])) {
title = [NSMutableString stringWithFormat:@"%@ (PR)",title];
[cell.textLabel setTextColor:[UIColor redColor]];
}
else if ([athleteMarks.eventSB integerValue] != 0
&& (![exceptions containsObject:athleteMarks.markInEvent])) {
title = [NSMutableString stringWithFormat:@"%@ (SB)",title];
[cell.textLabel setTextColor:[UIColor orangeColor]];
} else {
[cell.textLabel setTextColor:[UIColor grayColor]];
}
cell.textLabel.text = title;
cell.detailTextLabel.text = subTitle;
cell.indentationLevel = indentationLevelOne;
cell.indentationWidth = indentationForCell;
return cell;
}
如果需要,我可以向您发送实体的NSManagedObject子类的类别示例。此类别将照片和缩略图加载到CoreData实体中。第一次会很慢。但是,之后用户应该能够平滑地滚动TableView,然后所有更新的结果将自动加载。让我知道。
一个好处是CoreData处理所有内存管理。
祝你好运!答案 3 :(得分:0)
我没有足够的代表发表评论,所以这是一个帮助我的tableview滚动表现的答案:
-(void)tableView:(UITableView *)tableView
willDisplayCell:(UITableViewCell *)cell forRowAtIndexPath:(NSIndexPath *)indexPath
这两个技巧让我的桌子流得非常好。我从API服务获取图像数据,AFNETWORKING有一个非常棒的图像加载器,但由于图像在捆绑中,因此不需要。
答案 4 :(得分:0)
也许你可以试试SDWebImage
。它也是一种xamarin component
通过自动缓存到期处理来制作异步映像下载器和异步内存以及磁盘映像缓存。使用它可能意味着丢弃大量硬编写的代码,但它可能是值得的 - 你的代码将变得更加简单。在iOS中,您还可以在控制器的viewDidLoad中设置SDWebImageManager
:
- (void)viewDidLoad{
...
SDWebImageManager *manager = [SDWebImageManager sharedManager];
manager.delegate = self;
...
}
并将视图控制器设置为委托。然后,当调用以下委托方法时:
- (UIImage *)imageManager:(SDWebImageManager *)imageManager transformDownloadedImage:(UIImage *)image withURL:(NSURL *)imageURL
在缓存之前,您可以将图像缩放到适当大小的拇指。
希望有所帮助。
答案 5 :(得分:0)
Weel我有类似的问题,我的卷轴不顺畅。我在表中插入一个带有内部labelViews的变量UIImageView。 我所做的是为estimatedHeightforRowAtIndexPath更改方法HeightforRowAtIndexPath,现在滚动是平滑的。