10

我正在创建一个简单的 OS X FinderSync,它将一个菜单项添加到所有文件的控制/右键单击菜单中:

[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:@"/"]];

它对所有文件都很好(出现菜单项等),除了Oddly中的文件/Volumes,如果我手动创建一个目录/Volumes并在那里添加一些文件,当我右键单击时会出现 FinderSync 的菜单项。但是,对于任何已安装卷中的任何文件(即来自已安装的 .dmg),它都会失败:没有菜单项出现。

直接指定一个挂载的卷directoryURLs同样失败:

[FIFinderSyncController defaultController].directoryURLs = [NSSet setWithObject:[NSURL fileURLWithPath:@"/Volumes/SomeMountedDMG"]];

似乎其他人也有类似的问题,所以也许这是一个已知的错误/限制?

4

1 回答 1

9

Finder Sync 扩展监控的文件夹集不会跨越文件系统边界。(尽管 Apple 的文档中没有明确提及这一点,但可以通过经验验证,并且在 macOS 10.13.3 中仍然如此)。

由于预期的用例是监视由 Dropbox 等同步实用程序维护的特定文件夹,因此 Apple 可能不会将此视为限制。然而,许多开发人员将 Finder Sync 扩展作为向 Finder 中的顶级上下文菜单添加任意项目的一种方式(不受限于出现在服务子菜单中),即使Apple 明确不鼓励这种用法:

确保 Finder Sync 扩展点适合您计划提供的功能。最好的 Finder 同步扩展支持将本地文件夹的内容与远程数据源同步的应用程序。Finder Sync 并非用于修改 Finder 用户界面的通用工具。

要解决此限制并使扩展程序的菜单项可用于 Finder 中可见的任何项目,有必要执行以下操作:

  1. 扫描所有可见的挂载卷,并将对象的 directoryURLs属性初始化FIFinderSyncController为结果:

    import FinderSync
    
    let finderSync = FIFinderSyncController.default()
    if let mountedVolumes = FileManager.default.mountedVolumeURLs(includingResourceValuesForKeys: nil,
                                                                  options: .skipHiddenVolumes) {
        finderSync.directoryURLs = Set<URL>(mountedVolumes)
    }
    
  2. 由于 Finder Sync 扩展是长期存在的进程,因此请注册以获取有关卷被挂载、卸载和重命名的通知,并directoryURLs相应地更新:

    let notificationCenter = NSWorkspace.shared.notificationCenter
    notificationCenter.addObserver(forName: NSWorkspace.didMountNotification, object: nil, queue: .main) {
        (notification) in
        if let volumeURL = notification.userInfo?[NSWorkspace.volumeURLUserInfoKey] as? URL {
            finderSync.directoryURLs.insert(volumeURL)
        }
    }
    

    (处理卸载和重命名通知留给读者练习。)

于 2018-02-22T20:18:03.747 回答