如何在macOS Finder的NSExtensionRequestHandling中显示进度?
Finder扩展:进度显示与取消功能修复指南
关键修复步骤
1. 正确配置NSProgress对象
确保你的NSProgress实例设置总单位数,并启用取消支持,绑定取消回调到操作的终止逻辑:
class CustomOperation: Operation { let progress: Progress private let sourceUrl: URL private let completionHandler: (URL?, Error?) -> Void init(url: URL, completionHandler: @escaping (URL?, Error?) -> Void) { self.sourceUrl = url self.completionHandler = completionHandler // 根据实际任务工作量设置totalUnitCount,比如文件字节数、任务步骤数 self.progress = Progress(totalUnitCount: 100) super.init() // 启用取消功能 progress.isCancellable = true progress.cancellationHandler = { [weak self] in self?.cancel() } } }
2. 在任务执行中实时更新进度并检查取消状态
在Operation的main方法里,必须定期更新completedUnitCount,同时检查isCancelled状态,及时终止任务并调用完成回调:
override func main() { guard !isCancelled else { completionHandler(nil, NSError(domain: "com.your.extension", code: -1, userInfo: [NSLocalizedDescriptionKey: "操作已取消"])) return } // 示例:模拟分步执行的长时间任务 for step in 0...100 { guard !isCancelled else { break } // 更新进度 progress.completedUnitCount = Int64(step) // 替换为实际的任务逻辑(如文件处理、转换等) Thread.sleep(forTimeInterval: 0.05) } // 任务结束或取消时调用completionHandler if isCancelled { completionHandler(nil, NSError(domain: "com.your.extension", code: -1, userInfo: [NSLocalizedDescriptionKey: "操作已取消"])) } else { // 返回处理后的文件URL completionHandler(sourceUrl, nil) } }
3. 确保loadHandler的正确执行逻辑
在registerFileRepresentation的loadHandler中,返回的Progress必须是已正确配置的实例,且任务执行过程中不能阻塞loadHandler(你的当前代码已经做到了用队列异步执行,这点没问题,但要确保completionHandler最终一定会被调用):
itemProvider.registerFileRepresentation( forTypeIdentifier: kUTTypePDF as String, fileOptions: [.openInPlace], visibility: .all, loadHandler: { completionHandler -> Progress? in let op = self.newOperation(url: sourceUrl, completionHandler: completionHandler) self.queue.addOperation(op) return op.progress } )
4. 检查Info.plist配置
确保扩展的Info.plist中,NSExtension相关配置正确:
- 确认
NSExtensionActivationRule能正确匹配你要处理的文件类型 - 如果处理大文件,添加
NSExtensionActivationSupportsLargeFiles并设为YES
核心注意事项
- 不要将
NSProgress的totalUnitCount设为0,否则Finder会显示不确定进度(即“Estimate time remaining...”) - 必须在任务的每个关键步骤检查
isCancelled状态,否则取消操作不会生效 completionHandler必须在任务完成、失败或取消时调用,否则Finder会一直处于等待状态
内容的提问来源于stack exchange,提问作者Holtwick
相关产品推荐
相关产品推荐

