【问题标题】:Caching images in UITableView在 UITableView 中缓存图像
【发布时间】:2012-03-23 02:09:54
【问题描述】:

我正在将图片加载到与单元格文本对应的表格视图中,因此每个图像都不同。当用户向下滚动时,iOS 必须手动从 SSD 重新加载每个图像,因此滚动非常不稳定。如何缓存图像或防止需要重新创建表格视图单元格?其他人已经通过使用imageNamed: 解决了他们的问题,因为 iOS 会自动缓存您的图像,但我是从文档目录加载图像,而不是从应用程序包加载图像。我该怎么办?谢谢。

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {

    // Return the number of sections.
    return 1;

}


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {

    // Return the number of rows in the section.
    return [issues count];

}

// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {

    NSString *CellIdentifier = @"Cell";

    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    if (cell == nil) {

        cell = [[[UITableViewCell alloc] initWithFrame:CGRectZero reuseIdentifier:CellIdentifier] autorelease];

    }


    // Set up the cell...
    NSDictionary *dic = [self.issues objectAtIndex:indexPath.row];

    cell.text = [dic objectForKey:@"Date"];

    cell.imageView.image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/issues/%@/cover.png", documentsDirectory, [dic objectForKey:@"Directory Name"]]];

    return cell;

}

- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {

        return 150;

}

【问题讨论】:

  • 检查 UIImageLoader。它完全符合您的要求,只需添加两个文件到 xcode。它也非常容易理解,并且 repo 中有两个很棒的示例。 github.com/gngrwzrd/UIImageLoader

标签: iphone objective-c ios ipad uitableview


【解决方案1】:

那组字典是你的模型,所以它是一个自然的地方。棘手的部分是使您的模型可变。您可以使模型在类中可变,或者在缓存图像时跳过箍。我推荐前者,但在此处编码以匹配您现有的代码...

- (UIImage *)imageForIndexPath:(NSIndexPath *)indexPath {

    NSDictionary *dic = [self.issues objectAtIndex:indexPath.row];
    UIImage *image = [dic valueForKey:@"cached_image"];

    if (!image) {
        image = [UIImage imageWithContentsOfFile:[NSString stringWithFormat:@"%@/issues/%@/cover.png", documentsDirectory, [dic objectForKey:@"Directory Name"]]];
        NSMutableDictionary *updatedDictionary = [NSMutableDictionary dictionaryWithDictionary:dic];
        [updatedDictionary setValue:image forKey:@"cached_image"];
        NSMutableArray *updatedIssues = [NSMutableArray arrayWithArray:self.issues];
        [updatedIssues replaceObjectAtIndex:indexPath.row withObject:[NSDictionary dictionaryWithDictionary:updatedDictionary]];
        self.issues = [NSArray arrayWithArray:updatedIssues];
    }
    return image;
}

第一次滚动列表时会出现波动,之后会变得平滑。如果您不想在视图出现之前进行第一次切割并产生一点延迟,您可以提前遍历模型并强制加载:

for (int i=0; i<self.issues.count; i++) {
    NSIndexPath *indexPath = [NSIndexPath indexPathForRow:i inSection:0];
    (void)[self imageForIndexPath:indexPath];
}

最后一件事 - 另一种解决方案是一个可变数组来匹配您的问题数组。这可能很好,但通常情况下,我很高兴我在模型中包含了一些缓存计算。如果您发现自己在其他地方使用了该问题数组,您会很高兴您已经处理了所有图像。

【讨论】:

  • 谢谢,我会尽快尝试!除了复制和粘贴代码之外,我还有什么要做的吗?抱歉,我对 UITableViews 没有太多经验 :)
  • 我想不到。它应该作为第一步。下一步是让你的模型可变,这将简化和加快图像缓存方法中的工作。
  • @danh self.issues = [NSArray arrayWithArray:self.issues];必须是 self.issues = [NSArray arrayWithArray:updatedIssues];对吗?
  • @OzBoz 你是对的。谢谢。回读,不知道为什么我专注于改变模型。当时,我认为这会阻止 OP 将模型用作图像缓存,但现在我没有看到证据表明这是问题所在(即使在问题的编辑中)。也许这是一个早期的编辑?无论如何,很好的收获。会修正我的答案。
【解决方案2】:

除了缓存,您还可以考虑使用 Grand Central 调度在后台加载图像。加载单元格后,放置一个 UIActivityIndi​​cator,然后在单独的线程中将其替换为图像。

还可以查看有关图像口吃的相关答案: Non-lazy image loading in iOS

【讨论】:

猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2011-10-13
  • 1970-01-01
  • 2012-06-17
  • 1970-01-01
  • 2012-01-16
  • 1970-01-01
相关资源
最近更新 更多