macOS NSFileProvider无法获取文件项,下载后Finder打开提示文件为空
NSFileProvider fetchContents方法返回有效文件后Finder提示为空的修复方案
根因说明
该问题是NSFileProvider扩展开发中的常见实现错误,核心原因有两点:
- 临时文件权限不足:
NSFileProviderManager生成的临时目录默认仅对扩展进程本身开放读取权限,Finder作为外部进程访问时没有权限读取内容,会误判为0字节空文件 - 元数据没有同步更新:系统会缓存FileProvider Item的
contentVersion、documentSize等元数据,如果你返回了新的文件内容但没有同步更新对应item的元数据字段,系统会沿用旧的缓存信息,判断文件为空
修复步骤
- 复制文件到临时路径后,显式为文件添加全局读权限,保证外部进程可访问
- 回调
completionHandler前更新item的contentVersion、documentSize属性,和实际下载的文件信息匹配,刷新系统缓存 - 不要提前删除临时目录下的目标文件,保证completionHandler执行完成前文件可用
修正后参考代码
let task = downloadItem(named: filename) { url, error in guard let sourceURL = url, error == nil else { completionHandler(nil, nil, Error.fileDownloadFailed) return } let dataURL = NSFileProviderManager.default.temporaryDirectoryURL.appendingPathComponent(filename) do { // 先删除可能存在的旧临时文件 try? FileManager.default.removeItem(at: dataURL) try FileManager.default.copyItem(at: sourceURL, to: dataURL) // 显式设置全局读权限 try FileManager.default.setAttributes([.posixPermissions: 0o644], ofItemAtPath: dataURL.path) // 获取实际文件大小,更新item元数据 let fileAttrs = try FileManager.default.attributesOfItem(atPath: dataURL.path) let fileSize = fileAttrs[.size] as? Int ?? 0 item.documentSize = NSNumber(value: fileSize) // 生成新的contentVersion,可用文件哈希+时间戳保证唯一性 item.contentVersion = "\(fileSize)_\(Date().timeIntervalSince1970)" as NSString completionHandler(dataURL, item, nil) } catch { completionHandler(nil, nil, Error.fileDownloadFailed) } } task.progress.cancellationHandler = { completionHandler(nil, nil, NSError(domain: NSCocoaErrorDomain, code: NSUserCancelledError)) } return task.progress
内容的提问来源于stack exchange,提问作者eunjo_princess
相关产品推荐
相关产品推荐

