从磁盘块主线程

时间:2018-03-24 21:16:54

标签: swift uiimageview uiimage uikit

我有一组本地UIImage,我需要加载它们并在按下它们各自的单元格时按顺序显示。例如,我有20张热狗的图像组合在一起形成一个动画。当用户点击热狗单元格时,单元格的UIImageView应该为图像设置动画。

我知道如何使用UIImageView的{​​{1}}来实现动画效果。我的问题是从磁盘检索所有这些图像大约需要1.5秒并阻塞主线程。

我可以在animationImages中实例化一个帮助器类,它在后台线程上从磁盘加载这些图像,这样它们在需要时就会在内存中,但这看起来很糟糕。

有没有更好的方法可以快速从磁盘加载许多图像?

编辑:这些图片是插图,因此是.png。

Edit2:假设每个图像序列的总和为1 MB。我正在测试的图像尺寸比application(_:didFinishLaunchingWithOptions:)的@ 3x要求大33-60%。在我们的设计师获得正确的图像集之前,我等待确认最终的UIImageView大小,所以应该使用适当大小的资产显着缩短时间,但我也在物理iPhone上进行测试X

UIImageView

1 个答案:

答案 0 :(得分:1)

我建议您尝试UIImage(contentsOfFile:)而不是UIImage(named:)。在我的快速测试中发现它快了一个数量级。这有点可以理解,因为它做了很多事情(搜索资产,缓存资产等)。

// slow

@IBAction func didTapNamed(_ sender: Any) {
    let start = CFAbsoluteTimeGetCurrent()
    imageView.animationImages = (0 ..< 20).map {
        UIImage(named: filename(for: $0))!
    }
    imageView.animationDuration = 1.0
    imageView.animationRepeatCount = 1
    imageView.startAnimating()

    print(CFAbsoluteTimeGetCurrent() - start)
}

// faster

@IBAction func didTapBundle(_ sender: Any) {
    let start = CFAbsoluteTimeGetCurrent()
    let url = Bundle.main.resourceURL!
    imageView.animationImages = (0 ..< 20).map {
        UIImage(contentsOfFile: url.appendingPathComponent(filename(for: $0)).path)!
    }
    imageView.animationDuration = 1.0
    imageView.animationRepeatCount = 1
    imageView.startAnimating()

    print(CFAbsoluteTimeGetCurrent() - start)
}

请注意,这假定您拥有资源目录中的文件,并且您可能必须根据它们在项目中的位置进行相应的修改。另请注意,我避免在循环中执行Bundle.main.url(forResource:withExtension:),因为即使这样做也会对性能产生可观察的影响。