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

macCatalyst中从NSItemProvider获取文件URL始终失败的问题排查

问题:SwiftUI/macCatalyst拖放音视频文件无法获取URL

我开发了一款SwiftUI/macCatalyst应用,需要通过拖放功能接收音视频文件。在某视图中添加了如下修饰符以接收指定媒体文件:

.onDrop(of: ["public.movie","public.audio"], isTargeted: nil, perform: { providers in
    print(providers.first)
    
    let _ = providers.first?.loadObject(ofClass: URL.self, completionHandler: { (url, _) in
      print(url)
    })
    return true
})

拖放文件时,返回的provider打印信息为:

Optional(<NSItemProvider: 0x600002ae4b60> {types = (
"com.apple.m4a-audio",
"com.apple.finder.node" )})

该信息显示正常,但尝试获取文件URL时始终得到nil。请问这段代码存在什么问题?


解决方法

问题出在直接调用loadObject(ofClass: URL.self)无法处理Finder拖放的文件。从打印的provider类型可以看到包含com.apple.finder.node,这表示拖放的是Finder的文件引用,而非直接的URL对象,因此直接加载URL类型会返回nil。

正确的做法是使用loadFileRepresentation(forTypeIdentifier:)方法,它会将拖放的文件复制到应用的临时目录,并返回对应的文件URL。修正后的代码如下:

import MobileCoreServices // 需导入此框架以使用kUTTypeFileURL

// ...

.onDrop(of: ["public.movie","public.audio"], isTargeted: nil, perform: { providers in
    guard let provider = providers.first else { return false }
    
    provider.loadFileRepresentation(forTypeIdentifier: kUTTypeFileURL as String) { tempUrl, error in
        if let url = tempUrl {
            // 回调在后台线程,更新UI需切回主队列
            DispatchQueue.main.async {
                print("获取到的文件URL:\(url)")
                // 在这里处理音视频文件逻辑
            }
        } else if let error = error {
            print("加载文件失败:\(error.localizedDescription)")
        }
    }
    
    return true
})

额外注意点:

  • 必须导入MobileCoreServices框架,否则kUTTypeFileURL会报错;
  • loadFileRepresentation的回调运行在后台线程,若要更新SwiftUI视图状态,必须通过DispatchQueue.main.async切换到主队列执行。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 12:27:06