这个问题困扰了我一天多一点。要点是我有一个 Grouped UITableView 设置,这样每个部分只有一个条目。表格 View 中的每个单元格都包含一个占据单元格整个宽度和长度的 UIImageView。此外,每个单元格都具有指定的设置高度和宽度。
这是我的初始化方法:
- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
if (self) {
[[self layer] setMasksToBounds:NO];
[[self layer] setShouldRasterize:YES];
[[self layer] setRasterizationScale:[[UIScreen mainScreen] scale]];
[[self layer] setCornerRadius:10];
_bgCoverView = [[UIImageView alloc] initWithFrame:CGRectZero];
[_bgCoverView setClipsToBounds:YES];
[[_bgCoverView layer] setCornerRadius:10];
[_bgCoverView setContentMode:UIViewContentModeScaleAspectFill];
[self.contentView addSubview:_bgCoverView];
[_bgCoverView release];
//Init other parts of the cell, but they're not pertinent to the question
}
return self;
}
这是我的布局 subview :
- (void)layoutSubviews{
[super layoutSubviews];
if (!self.editing){
[_bgCoverView setFrame:CGRectMake(0, 0, tableViewCellWidth, self.contentView.frame.size.height)];
}
}
这是我的单元格 setter :
- (void)setGroup:(Group*)group{
//Set background cover for the contentView
NSSet *usableCovers = [[group memories] filteredSetUsingPredicate:[NSPredicate predicateWithFormat:@"pictureMedData != nil || pictureFullData != nil || (pictureMedUrl != nil && NOT pictureMedUrl contains[cd] '/missing.png')"]];
Memory *mem = [usableCovers anyObject];
[_bgCoverView setImage:[UIImage imageWithContentsOfFile:@"no_pics_yet.png"]];
if (mem != nil){
[Folio cacheImageAtStringURL:[mem pictureMedUrl] forManagedObject:mem withDataKey:@"pictureMedData" inDisplay:_bgCoverView];
}
}
这是我认为性能问题的地方。首先是过滤后的 set 调用。如果集合中有很多对象,这可能会减慢速度。但是,对象往往相对较少。此外,当我删除这行代码时,我没有看到任何性能变化,所以这不太可能。
所以,这几乎就剩下我的缓存方法(位于辅助类中)。方法如下:
+(void)cacheImageAtStringURL:(NSString *)urlString forManagedObject:(NSManagedObject*)managedObject withDataKey:(NSString*)dataKey inDisplay:(NSObject *)obj{
int objType = 0; //Assume UIButton
if (obj == nil)
objType = -1;
else if ([obj isKindOfClass:[UIImageView class]])
objType = 1; //Assign to UIImageView
NSData *data = (NSData*)[managedObject valueForKey:dataKey];
if ([data bytes]){
if (objType == 0) [(UIButton*)obj setBackgroundImage:[UIImage imageWithData:data] forState:UIControlStateNormal];
else if (objType == 1) [(UIImageView*)obj setImage:[UIImage imageWithData:data]];
return;
}
//Otherwise, do an ASIHTTPRequest and set the image when it's returned, save the data into core data so that we get a cache hit the next time.
}
无论图像是否缓存,在该 View 上向下滚动都存在重大性能问题。如果我注释掉缓存方法,它会很好用。此外,调用此方法的其他 View 运行缓慢,所以我很确定它在这里。
不过,我还要说的是,我也对 cornerRadius 代码持怀疑态度,但是,我听说如果将 shouldRasterize 设置为 YES,它会导致性能加速。不过,我不确定这是否 100% 正确,或者我的实现是否有问题。
如有任何帮助,我们将不胜感激。
更新
仍未 100% 修复,但我们正在实现目标。
必须根据请求设置这些变量:
[request setCachePolicy:ASIOnlyLoadIfNotCachedCachePolicy];
[request setCacheStoragePolicy:ASICachePermanentlyCacheStoragePolicy];
第一个告诉缓存仅在图像未被缓存时对服务器执行 ping 操作。第二个告诉缓存在应用程序的生命周期内永久存储图像。
这让我走到了尽头。一些图像立即加载,而另一些图像加载缓慢。我做了更多研究并在我的应用委托(delegate)中添加了这些代码行:
[[ASIDownloadCache sharedCache] setShouldRespectCacheControlHeaders:NO];
[ASIHTTPRequest setDefaultCache:[ASIDownloadCache sharedCache]];
第一行很关键。 ASIHTTPRequest 的默认操作是遵循 Web 服务器告诉您的内容。因此,如果它在其 header 中告诉您不要缓存响应,它就不会。这一行覆盖了它。现在,这在我的 iOS 模拟器上运行得非常好。然后,我在我的4S上试了一下,又慢了。
原因是因为我在请求中设置了一段代码,在成功检索图像后,我会将其保存到 Core Data。每次都会触发此调用,即使对于缓存的请求也是如此。
这是因为 ASIHTTPRequest 仍然会发出请求,无论它是否使用您数据的缓存副本。如果它有一个缓存副本,它就不会向服务器发出请求,而是用缓存数据填充其请求对象的响应数据。因此,在我的 block 负责显示工作后,我调用:
if ([request didUseCachedResponse]) return;
这在 4S 和 4 上运行良好。但是,3GS 仍然非常慢 :-(。
这是因为 ASIHTTPRequest 使用的是我的 NSData 的缓存副本,而不是我的 UIImage。因此,每次使用缓存时都需要重新创建图像。这是有道理的,因为 ASIHTTPRequest 只返回数据,并且不知道您之后将如何处理数据,因此它总是会调用您在返回请求时设置的代码。因为我的代码块从数据转换图像,所以这就是我得到的。
前进的道路
我认为要获得我想要的性能加速,有必要实现自定义 UIImage 缓存。如果我们在缓存中找到该文件,我们将返回 UIImage 对象。如果没有,那么我们创建一个请求并在返回时将其保存在缓存中。
最佳答案
shouldRasterize
的提示是有效的,尽管根据我的经验,这会显着降低图形质量。此外,由于像 iOS4.3 左右(不记得了)他们极大地改进了 cornerRadius
调用,我上次需要为此类问题激活光栅化已经很长时间了。
您可以随时停用 cornerRadius
并查看它的性能。
不过,我真正想告诉你的是 ASIHTTPRequest 具有内置的缓存支持,请参阅
http://allseeing-i.com/ASIHTTPRequest/How-to-use#using_a_download_cache
尝试一下,它对我来说完美无缺。考虑哪种缓存策略最适合您的需求。当然,如果您需要 CoreData 中的图像,则必须插入它们,但我不会尝试从 CoreData 手动缓存它们。
哦,还有别的……ASIHTTPRequest 不再处于开发阶段,您可能需要考虑切换到另一个框架(如 AFNetworking)。 ASIHTTPRequest 例如不支持 ARC。
关于iphone - 使用 ASIHTTPRequest 的 UITableViewCell 中的 UIImageView 性能,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9380584/