退出应用程序后,按需资源真的仍然存在吗?

Does On demand resource really persisted after quitting the app?

提问人:iroh 提问时间:6/19/2023 最后编辑:iroh 更新时间:6/19/2023 访问量:40

问:

我已将 NSBundleResourceRequest 对象创建为该类的实例成员。 如果我退出应用程序,则会解除分配请求对象。根据苹果文档,如果请求对象被解除分配,则系统会处理下载资产的控制权,并且数据可能会被永久删除。我的疑问是,如果游戏对每个关卡的元数据使用 ODR,我们就不会在每次重新打开应用程序时都下载资源。下载资产后,我们是否必须手动保存 ODR?

class ViewController: UIViewController {
    var request = NSBundleResourceRequest(tags: Set(arrayLiteral: "prefetch"))
    
    lazy var imageView1:UIImageView = {
        let imageView  = UIImageView(image: UIImage(named: "car"))
        imageView.layer.borderColor = UIColor.red.cgColor
        imageView.layer.borderWidth = 2
        return imageView
    }()
    let label = UILabel()
    lazy var  imageView2:UIImageView = {
        let imageView  = UIImageView(image:UIImage(named: "hd1"))
        imageView.layer.borderColor = UIColor.red.cgColor
        imageView.layer.borderWidth = 2
        return imageView
    }()
    
    lazy var imageView3:UIImageView = {
        let imageView  = UIImageView(image:UIImage(named: "hd2"))
        imageView.layer.borderColor = UIColor.red.cgColor
        imageView.layer.borderWidth = 2
        return imageView
    }()
    
    let button:UIButton = {
//        let config = UIButton.Configuration.bordered()
        let button = UIButton()
        button.setTitleColor(.white, for: .normal)
        button.backgroundColor = .green
        button.setTitle("Load HD image", for: .normal)
        return button
    }()
    
    override func loadView() {
        super.loadView()
        loadImage()
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        configureImageViews()
        fetchImage()
    }

    func configureImageViews(){
        view.addSubview(imageView1)
        view.addSubview(imageView2)
        view.addSubview(imageView3)
        view.addSubview(button)
        view.addSubview(label)
        
        label.translatesAutoresizingMaskIntoConstraints = false
        imageView1.translatesAutoresizingMaskIntoConstraints = false
        imageView2.translatesAutoresizingMaskIntoConstraints = false
        imageView3.translatesAutoresizingMaskIntoConstraints = false
        button.translatesAutoresizingMaskIntoConstraints = false

        label.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor).isActive = true
        label.leadingAnchor.constraint(equalTo: view.leadingAnchor).isActive = true
        label.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: -10).isActive = true
        label.heightAnchor.constraint(equalToConstant: 40).isActive = true
        
        imageView1.topAnchor.constraint(equalTo: label.safeAreaLayoutGuide.bottomAnchor).isActive = true
        imageView1.heightAnchor.constraint(equalToConstant: 200).isActive = true
        imageView1.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView1.widthAnchor.constraint(equalToConstant: 200).isActive = true
        
        imageView2.topAnchor.constraint(equalTo: imageView1.safeAreaLayoutGuide.bottomAnchor,constant: 20).isActive = true
        imageView2.heightAnchor.constraint(equalToConstant: 200).isActive = true
        imageView2.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView2.widthAnchor.constraint(equalToConstant: 200).isActive = true
        
        imageView3.topAnchor.constraint(equalTo: imageView2.safeAreaLayoutGuide.bottomAnchor,constant: 20).isActive = true
        imageView3.heightAnchor.constraint(equalToConstant: 200).isActive = true
        imageView3.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        imageView3.widthAnchor.constraint(equalToConstant: 200).isActive = true
        
        button.topAnchor.constraint(equalTo: imageView3.safeAreaLayoutGuide.bottomAnchor,constant: 20).isActive = true
        button.heightAnchor.constraint(equalToConstant: 40).isActive = true
        button.centerXAnchor.constraint(equalTo: view.centerXAnchor).isActive = true
        button.widthAnchor.constraint(equalToConstant: 200).isActive = true
        
        button.addTarget(self, action: #selector(buttonDidTapped), for: .touchUpInside)
    }
    
    func fetchImage(){
        request.endAccessingResources()
        self.request.conditionallyBeginAccessingResources(completionHandler: {isImageAvailable in
            if isImageAvailable == true{
                //image already available
                print("--> Local data available")
                self.loadImage()
                DispatchQueue.main.async {
                    self.label.text = "Local data available"
                }
            }else{
                //download from app store
                self.request.beginAccessingResources(completionHandler: {error in
                    if let error{
                        print("--> something went wrong")
                        self.label.text = "something went wrong"
                        return
                    }
                    DispatchQueue.main.async {
                        self.label.text = "fetching remote"
                    }
                    self.loadImage()
                })
            }
            
        })
    }

    
    func loadImage(){
        DispatchQueue.main.async {
            self.imageView1.image = UIImage(named: "car")
            self.imageView2.image = UIImage(named: "hd1")
            self.imageView3.image = UIImage(named: "hd2")
        }
    }
    
   @objc func buttonDidTapped(){
        request = NSBundleResourceRequest(tags: Set(arrayLiteral: "hd1"))
       fetchImage()
    }
}


我希望我们如何确保ODR数据不会再次下载?

iOS Swift Foundation On-Demand-Resources ios部署

评论


答:

0赞 matt 6/19/2023 #1

对特定 ODR 资源的使用必须用对 和 的调用括起来,在这两个调用之间保留 NSBundleResourceRequest。这就是你所知道的,也是你需要知道的。beginAccessingResourcesendAccessingResources

如果您的应用程序在调用之前终止,则在重新启动时,您显然没有 NSBundleResourceRequest 实例;但这并不重要,因为您只需继续遵循有关如何访问资源的规则即可。启动后,立即创建一个 NSBundleResourceRequest 并调用 ;您的资源可能仍然存在,因此您将立即获得访问权限,并且您保留的 NSBundleResourceRequest 会使资源继续存在,直到您最终通过说 .endAccessingResourcesbeginAccessingResourcesendAccessingResources

评论

0赞 iroh 6/20/2023
你提到.如果系统需要内存,它可能会在我们的应用程序关闭时删除我们的资源。这是对的吗?your resources are probably still present