如何获取Apple ODR资源的URL路径?NSBundleResourceRequest读取返回nil如何解决
问题核心原因
你无法获取路径的根本原因是:所有存放在Assets.xcassets中的资源(包括你添加的data类型资源)都会在编译时被打包进统一的Assets.car文件,不会以独立文件的形式存在于App Bundle中,因此调用url(forResource:)/path(forResource:)肯定返回nil。
解决方案
你可以根据使用场景二选一:
方案1:资源继续保留在Assets.xcassets中
如果你不想调整资源存放位置,不需要直接访问文件路径,只需要读取资源内容,可以通过NSDataAsset直接读取:
// 确保在conditionallyBeginAccessingResources或者beginAccessingResources的成功回调内执行 guard let dataAsset = NSDataAsset(name: "myFile", bundle: req.bundle) else { // 资源不存在的异常处理 return } let resourceData = dataAsset.data
如果你的下游函数必须传入文件路径,可以先将读取到的Data写入沙盒临时目录/文档目录,再将写入后的路径传给下游:
let tempDir = NSTemporaryDirectory() as NSString let targetPath = tempDir.appendingPathComponent("myFile.data") do { try resourceData.write(to: URL(fileURLWithPath: targetPath)) // 在这里把targetPath传给你需要的函数 } catch { // 写入失败处理 }
方案2:调整资源存放位置,直接获取独立文件路径
如果你需要直接拿到ODR中资源的原始文件路径,不要把资源放到Assets.xcassets里:
- 把
myFile.data直接拖到项目根目录/自定义的资源目录下,勾选「Copy items if needed」,确认勾选了对应Target的成员资格 - 给这个资源设置你要用的ODR标签
- 之后就可以直接通过资源请求的bundle拿到路径:
guard let resourceUrl = req.bundle.url(forResource: "myFile", withExtension: "data") else { // 异常处理 return } let resourcePath = resourceUrl.path // 直接传入路径给下游函数使用
注意事项
- 持有
NSBundleResourceRequest实例:资源访问期间不要释放assetsPack,也不要提前调用endAccessingResources(),否则已下载的资源会被系统回收,无法正常读取 - 如果你的资源存放在项目的子文件夹下,调用
url(forResource:)时需要补充subdirectory参数,传入资源所在的文件夹名称 - 优先使用
req.bundle读取资源,不要直接用Bundle.main,避免资源归属错误导致读取失败
内容的提问来源于stack exchange,提问作者inoxious
相关产品推荐
相关产品推荐

