You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

使用Apple ODR下载的图片无法显示,如何正确加载?

ODR资源加载问题

我在Xcode的资源标签中为一组图片添加了"cat-images"标签,测试时执行以下代码成功获取资源:

let resourceRequest = NSBundleResourceRequest(tags: Set(["cat-images"]))
resourceRequest.conditionallyBeginAccessingResources { (resourcesAvailable) in
    if resourcesAvailable {
        completion(nil)
    } else {
        resourceRequest.beginAccessingResources { (error) in
            completion(error)
        }
    }
}

但尝试显示其中一张图片时,使用UIImage(named: "siamese.png").map { Image(uiImage: $0) }及自定义的加载方法:

extension Image {
    static func loadFromODR(resourceName: String) -> Image? {
        let components = resourceName.split(separator: ".")
        let name = String(components[0])
        let ext = String(components[1])
        print("attempting odr image: \(name).\(ext)")
        guard let path = Bundle.main.path(forResource: name, ofType: ext),
              let image = UIImage(contentsOfFile: path) else {
            print("could not find: \(name).\(ext)")
            return nil
        }
        return Image(uiImage: image)
    }
}

均无法找到图片。请问ODR资源是否需要特殊的加载方式?是否每个图片都需要单独设置ODR标签?


问题解答

  • 不需要为每个图片单独设置ODR标签,用组标签"cat-images"批量关联资源的方式完全可行。

  • ODR资源加载的关键修正点:

    1. 移除文件名扩展名:使用UIImage(named:)时不要带.png后缀,正确写法是UIImage(named: "siamese")——该方法会自动匹配对应格式的资源,带扩展名反而会导致资源匹配失败。
    2. 确保异步回调后再加载:beginAccessingResources是异步操作,必须在其回调确认资源可用后,再执行图片加载逻辑。如果后续加载逻辑没等待回调完成,会出现资源未下载就查找的情况。
    3. 检查资源配置:
      • 确认图片的Resource Tags确实关联到"cat-images",且Target Membership勾选了当前运行的Target;
      • 在项目Target的General页面,确认On Demand Resources已启用,对应标签的资源被正确包含;
      • 优先用真机测试:模拟器会直接使用本地资源,无法复现真实ODR下载流程,容易排查错误。
  • 修正后的加载示例:

let resourceRequest = NSBundleResourceRequest(tags: Set(["cat-images"]))
resourceRequest.conditionallyBeginAccessingResources { [weak self] resourcesAvailable in
    if resourcesAvailable {
        self?.displayCatImage()
    } else {
        resourceRequest.beginAccessingResources { error in
            guard error == nil else {
                print("ODR资源下载失败: \(error!)")
                return
            }
            self?.displayCatImage()
        }
    }
}

func displayCatImage() {
    // 正确加载方式:不带扩展名
    if let uiImage = UIImage(named: "siamese") {
        let image = Image(uiImage: uiImage)
        // 这里更新UI显示图片
    } else {
        print("无法找到siamese图片")
    }
}
  • 自定义加载方法的优化:如果必须用contentsOfFile加载,要注意资源名含多个.的情况(比如siamese.v1.png),原拆分逻辑会出错,可改用URL拆分扩展名:
extension Image {
    static func loadFromODR(resourceName: String) -> Image? {
        let url = URL(fileURLWithPath: resourceName)
        let name = url.deletingPathExtension().lastPathComponent
        let ext = url.pathExtension
        print("attempting odr image: \(name).\(ext)")
        guard let path = Bundle.main.path(forResource: name, ofType: ext),
              let image = UIImage(contentsOfFile: path) else {
            print("could not find: \(name).\(ext)")
            return nil
        }
        return Image(uiImage: image)
    }
}

内容的提问来源于stack exchange,提问作者soleil

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.28 22:52:48