iphone - 使用 ASIHTTPRequest 的 UITableViewCell 中的 UIImageView 性能

标签 iphone ios caching uitableview uiimageview

这个问题困扰了我一天多一点。要点是我有一个 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/

相关文章:

iphone - UIButton 文本颜色 RGB

ios - 将数据从 UIPickerView 传递回其委托(delegate)

iphone - iOS:UITableView 说明

iphone - 在 Objective-C++ 中将 NSLog 与 C++ 对象一起使用

ios - 在用户选择时动态删除自定义 UIView/在 ios swift 中突出显示

iphone - 检查 NSDictionary 中的键是否为空

ios - 加载未显示的 UITableViewCells

c# - 如何修改CPU Cache L1、Cache L2、Cache L3?

java - 通过 Java 小程序加密表单上的文本字段;浏览器正在缓存加密文本;如何缓存明文?

c# - 使用 System.Web.Caching.Cache