UIImage是否缓存图像?

21
UIImage *img = [[UIImage alloc] initWithContentsOfFile:@"xx.jpg"]
UIImage *img = [UIImage imageNamed:@"xx.jpg"]

在第二种类型中,图片会被缓存吗? 而在第一种类型中,图片不会被缓存?
4个回答

34
  • -initWithContentsOfFile: 方法创建新的图片时不使用缓存,这是一种普通的初始化方法。

  • +imageNamed: 方法使用缓存。以下是来自 UIImage 参考文档 的说明:

    该方法在系统缓存中查找指定名称的图像对象,并返回该对象(如果存在)。如果匹配的图像对象尚未在缓存中,则此方法从指定文件加载图像数据、缓存它,然后返回结果对象。

    UIImage 会保留已加载的图像,使其保持活动状态,直到低内存条件导致缓存被清除。

Swift 更新: 在 Swift 中,UIImage(named: "...") 函数是使用缓存的函数。


缓存会导致额外的资源使用还是只是指向该对象的指针? - raghul
1
@raghul UIImage 只会保留您现有的图像,在您释放它后仍然保持活动状态,直到低内存条件导致缓存被清除。 - iHunter
4
我已模拟低内存,但在iOS 10中缓存并未清除。 - Yitzchak

9

我想在这里分享一些有关路径名问题的解决方法。这是一个可以放在UIImage类别上的方法。

+(UIImage *)imageNamed:(NSString *)name cache:(BOOL)cache {
    if (cache)
        return [UIImage imageNamed:name];
    name = [[NSBundle mainBundle] pathForResource:[name stringByDeletingPathExtension] ofType:[name pathExtension]]; 
    UIImage *retVal = [[UIImage  alloc] initWithContentsOfFile:name];
    return retVal;
}

如果您没有简单的方法来切换到缓存,您可能最终只使用`imageNamed`。在大多数情况下,这是一个很大的错误。请参见这个很棒的答案以获取更多详细信息(并点赞问题和答案!)。

1
如果您希望在存在多个句点的情况下不会出现错误,您可以使用 newName = [[NSBundle mainBundle] pathForResource:[name stringByDeletingPathExtension] ofType:[name pathExtension]];UIImage *retVal = [[UIImage alloc] initWithContentsOfFile:newName]; - lnafziger
1
注意:如果包中仅包含@2x版本的图像,则此代码将无法正常工作,因为pathForResource不会检查@2x。否则,这是一个很好的解决方案。 - Joel
1
你救了我的命! - Yitzchak
@Yitschak 很高兴它有帮助,感谢您的评论!如果您正在使用Swift,请也看看Haneke。 - Dan Rosenstark
https://github.com/Haneke/HanekeSwift和https://github.com/Haneke/Haneke。值得花时间设置。 - Dan Rosenstark

1

@Dan Rosenstark 用Swift回答...

extension UIImage {

    static func imageNamed(name: String, cache: Bool) -> UIImage? {
        if (cache) {
            return UIImage(named: name)
        }

        // Using NSString for stringByDeletingPathExtension
        let fullName = NSString(string: name)
        let fileName = fullName.stringByDeletingPathExtension
        let ext = fullName.pathExtension
        let resourcePath = NSBundle.mainBundle().pathForResource(fileName, ofType: ext)

        if let path = resourcePath {
            return UIImage(contentsOfFile: path)
        }
        return nil
    }
}

0

没错,第二个项目已被缓存。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接