【问题标题】:Trying to cache uiImages in dictionary, doesn't seem to affect loading time尝试在字典中缓存 uiImages,似乎不会影响加载时间
【发布时间】:2011-06-17 18:50:47
【问题描述】:

我正在使用标准缓存方法来缓存从 Documents 目录加载的一些 UIImages。图像显示在 UITableView 中。它们非常大——图像本身高达 600x600,并以 240x180 的图像视图显示(在视网膜显示器上,因此分辨率差异不大)。

当新单元格即将出现在屏幕上时,实时加载图像会导致一些延迟。所以我在处理图像的对象中实现了一个缓存方法:

- (UIImage *)imageWithStyle:(NSString *)styleName {
    NSLog(@"looking for image %@", self.imageFileName);

    /* if we have a cached image in dictionary, return it */
    if (imageCache == nil) imageCache = [[NSMutableDictionary alloc] init];
    UIImage *returnImage = [imageCache objectForKey:styleName];
    if (returnImage != nil) {
        NSLog(@"returning cached image");
        return returnImage;
    }

    /* otherwise, look for image at path */
    NSString *path = [self cacheFilePathWithStyle:styleName];
    UIImage * originalImage = [[UIImage alloc] initWithContentsOfFile:path];

    /* if image doesnt exist at path, start download and return nil */
    if (originalImage == nil) {
        NSLog(@"image not found. downloading.");
        [self downloadImageFromS3];
        return nil;
    }

    /* found image at path */

    /* scale image for screen */
    if ([[UIScreen mainScreen] respondsToSelector:@selector(scale)] && [[UIScreen mainScreen] scale] == 2){
        returnImage = [UIImage imageWithCGImage:[[originalImage autorelease] CGImage] scale:2.0 orientation:UIImageOrientationUp];
        NSLog(@"scaling image for retina");
    } else {
        returnImage = [originalImage autorelease];
        NSLog(@"image scaled for standard resolution");
    }

    /* cache image in dictionary */
    NSLog(@"caching image");
    [imageCache setObject:returnImage forKey:styleName];

    return returnImage;
}

在 tableview 出现在屏幕上之前,我强制所有图像处理对象运行此缓存方法,以确保图像存在于字典中,以便在需要显示时检索它们。通过 NSLog,我可以看到一切正常。

我现在获得了无延迟的性能,但只有在图像出现在屏幕上一次之后。因此,当我最初看到 tableview 时,我向下滚动并且 NSLogs 告诉我正在从缓存中检索图像,但我仍然得到相同的加载延迟。一个单元格在屏幕上出现一次后,它就会立即加载。

这里有什么我遗漏的吗?我还需要做些什么来实际缓存图像吗?加载它并将其放入字典似乎并没有解决问题。

谢谢!

更新

我现在已经放弃了。有一些尝试通过在新的上下文中绘制图像来强制加载图像,但我目前还不熟悉核心图形编程。我尝试了一些人们共享的代码,但没有成功。

相反,我将在 tableview 滚动时显示图像的低分辨率版本,并在 tableview 通过其委托方法宣布停止滚动时加载高分辨率版本。至少我知道这种方法适用于任意数量的图像。

【问题讨论】:

    标签: caching ios uitableview uiimage


    【解决方案1】:

    来自-[UIImage initWithContentsOfFile:]的文档:

    此方法将图像数据加载到内存中并将其标记为可清除。如果数据被清除并需要重新加载,则图像对象会从指定路径再次加载该数据。

    我的猜测是,通过将所有图像加载到内存中,您的应用会消耗太多内存,导致 UIImage 类释放它可以稍后从文件重新加载的图像数据。

    【讨论】:

    • 感谢您的回复!嗯,这似乎是一个不错的猜测,但是一旦我滚动浏览了整个列表视图(大约 30 张图像),我就不再有加载延迟。因此,似乎图像在此时全部缓存,没有任何问题。我会先尝试只缓存前 10 张左右的图片,看看是否有什么不同。
    • 如果我只缓存几张图片没有区别。我还尝试使用不缓存图像的 imageWithContentOfFile(无论如何都是一个好主意,因为我自己缓存图像)。没有运气。
    • 也许UIImage 会延迟加载图像(即,它仅在它们被绘制在屏幕上时才加载它们)。文档中还有其他内容,但这可以解释您所看到的行为。
    • 谢谢,奥莱。我想你是正确的。我将寻找一种以某种方式强制加载的方法。
    • 我正在尝试像this 这样的解决方案,但还没有运气。
    【解决方案2】:

    如果您使用[UIImage imageNamed:],它将为您完成所有这些缓存业务。无需滚动您自己的缓存,然后怀疑它是否有效。

    使用这种方法的好处和坏处。好处:如果您使用相同的图像文件两次,它实际上不会加载它两次,从而节省您的内存。缺点:缓存对内存有很大的影响,无论您是否自己滚动,您都需要非常努力地考虑这样做。

    【讨论】:

    • 感谢您的回复!我正在从文档目录加载图像,所以 imageNamed: 不是一个直接的选择。这就是我以这种方式缓存图像的原因。但是,正如 Ole 指出的那样,我不认为 initWithContentOfFile 也会缓存图像。也许我在这里太努力了……
    猜你喜欢
    • 2016-08-23
    • 2013-08-12
    • 1970-01-01
    • 1970-01-01
    • 2012-03-20
    • 1970-01-01
    • 1970-01-01
    • 2014-07-05
    • 2013-06-28
    相关资源
    最近更新 更多