Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/16.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 从磁盘块主线程加载多个UIImage_Swift_Uiimageview_Uiimage_Uikit - Fatal编程技术网

Swift 从磁盘块主线程加载多个UIImage

Swift 从磁盘块主线程加载多个UIImage,swift,uiimageview,uiimage,uikit,Swift,Uiimageview,Uiimage,Uikit,我有一组本地UIImages,当点击它们各自的单元格时,我需要按顺序加载和显示它们。例如,我有20个热狗的图像,它们组合在一起形成动画。当用户轻触热狗单元格时,单元格的UIImageView应设置图像动画 我知道如何使用UIImageView的animationImages来实现动画。我的问题是,从磁盘检索所有这些映像需要约1.5秒,并且会阻塞主线程 我可以在应用程序中实例化一个helper类(uquot:didfishlaunchingwithoptions:),该类可以在后台线程上从磁盘加载

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


我知道如何使用
UIImageView
animationImages
来实现动画。我的问题是,从磁盘检索所有这些映像需要约1.5秒,并且会阻塞主线程

我可以在
应用程序中实例化一个helper类(uquot:didfishlaunchingwithoptions:)
,该类可以在后台线程上从磁盘加载这些图像,以便在需要时将它们保存在内存中,但这似乎有点不太妥当

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


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

Edit2:假设每个图像序列的总和为1MB。我测试的图像尺寸比
UIImageView
的@3x要求大33-60%。我正在等待确认最终的
UIImageView
大小,然后再从我们的设计师那里获得正确的图像集,因此使用适当大小的资产应该可以大大缩短时间,但我也在物理iphonex上进行测试

class ViewModel {

    func getImages() -> [UIImage] {

        var images: [UIImage] = []

        for i in 0..<44 {
            if let image = UIImage(named: "hotDog\(i).png") {
                images.append(image)
            }
        }

        return images

    }
}

class ViewController: UIViewController {

    private var viewModel: ViewModel!

    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {

        let cell = tableView.cellForRow(at: indexPath) as! CustomCell
        let images = viewModel.getImages()
        cell.animateImageView(withImages: images)

    }
}

class CustomCell: UITableViewCell {

    @IBOutlet weak var imageView: UIImageView!

    func animateImageView(withImages images: [UIImage]) {

        imageView.image = images.last
        imageView.animationImages = images
        imageView.animationDuration = TimeInterval(images.count / 20)
        imageView.animationRepeatCount = 1
        imageView.startAnimating()

    }
}
类视图模型{
func getImages()->[UIImage]{
变量图像:[UIImage]=[]

对于0中的i..我建议您尝试
UIImage(contentsOfFile:)
而不是
UIImage(name:)
。在我的快速测试中,我发现它的速度快了一个数量级以上。这在某种程度上是可以理解的,因为它做了很多事情(搜索资产、缓存资产等)

//慢
@iAction func didTapNamed(u发送方:任意){
let start=CFAbsoluteTimeGetCurrent()
imageView.animationImages=(0..<20).map{
UIImage(名称:filename(用于:$0))!
}
imageView.animationDuration=1.0
imageView.animationRepeatCount=1
imageView.startAnimating()
打印(CFAbsoluteTimeGetCurrent()-start)
}
//更快
@iAction func didTapBundle(u发送方:任意){
let start=CFAbsoluteTimeGetCurrent()
让url=Bundle.main.resourceURL!
imageView.animationImages=(0..<20).map{
UIImage(contentsOfFile:url.appendingPathComponent(文件名:$0)).path)!
}
imageView.animationDuration=1.0
imageView.animationRepeatCount=1
imageView.startAnimating()
打印(CFAbsoluteTimeGetCurrent()-start)
}

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

“我的问题是,从磁盘检索所有这些映像需要约1.5秒,并且会阻塞主线程"与图像视图的大小相比,这些图像是否有不必要的巨大?我也很好奇为什么加载这些图像需要这么长时间。我觉得问题更像是您正在将它们加载到背景线程中。我建议使用仪器来查看真正花时间的内容。此外,您还没有展示您的行为ual代码使得无法以任何明确的方式提供帮助…预加载图像可以解决此问题(虽然您不必返回到
didfishlaunchwithoptions
;为什么不在加载视图时触发此操作;这感觉像是视图或视图控制器的责任,而不是应用程序代理)。但是如果它们需要1.5秒,它们一定很大和/或很多,我也会非常担心内存使用的峰值。延迟可能只是几个问题之一。@matt See Edit2…@Rob preload听起来可行,但我有太多具有独特图像集的单元格来加载它们。很好的解决方案。对我来说大约快11.7倍1.谢谢你,罗伯。
// 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)
}