OS X FinderSync 'fails' for /Volumes

OS X FinderSync 'fails' for /Volumes

我正在创建一个简单的 OS X FinderSync,它向所有文件的 control/right-click 菜单添加一个菜单项:

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

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

directoryURLs 中直接指定已安装的卷同样失败:

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

似乎 others 有过类似的问题,所以这可能是已知的 bug/limitation?

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

由于这些扩展的预期用例是监视 Finder 何时显示由同步实用程序(如 Dropbox)维护的特定文件夹,因此 Apple 可能不会将此行为视为限制。但是,许多开发人员将 Finder Sync 扩展实现为一种将任意项目添加到 Finder 中的 top-level 上下文菜单的方式(不限于出现在服务子菜单中),即使这种用法是 explicitly discouraged by Apple

Make sure the Finder Sync extension point is appropriate for the functionality you plan to provide. The best Finder Sync extensions support apps that sync the contents of a local folder with a remote data source. Finder Sync is not intended as a general tool for modifying the Finder’s user interface.

要解决此限制并使扩展的菜单项可用于 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 扩展是 long-lived 个进程,请注册 用于安装、卸载和重命名卷的通知, 并相应地更新 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)
        }
    }
    
    (处理卸载和重命名通知留作练习 对于 reader.)