通常,你不会遇到这个问题,直到你需要写一个后台程序……
我们都知道 macOS 有一个全局的 Dock,这个东西上会显示所有正在运行的程序,但如果你的程序是一个菜单栏小程序,或者是一个……输入法,那你肯定不想让这个 app 的图标显示在Dock 上,因为这类 app 是要持续在后台运行的。
这时候我们就可以在 Info.plist 中写 LSBackgroundOnly 字段,这样这个 app 就会在后台运行,没有 Dock 图标,也不会在 cmd+tab 的切换选项中显示出来了。这也是苹果官方示例中的配置——但这么做长久以来伴随着一个问题,那就是如果你这个 app 还是需要显示必要的设置界面的话,那这个界面会永远在所有窗口的最下方,也就是说,窗口一弹出就立即被挡住了。甚至,除了标准窗口,其他任何警告弹窗,都是无法显示的,除非先有一个标准窗口出现,且用户点击了一下该窗口的任何位置……
上文这些前提导致了很多问题,我不得不内嵌另外一个 app 来作为落格输入法的专门设置软件,然后两者之间使用 xpc 通信,真的是令人绝望。
直到今天 TIL,我发现原来可以使用 NSApplication.shared.setActivationPolicy(.accessory) 在程序中动态改变自己的运行级别,可以动态修改自己为普通 regular 模式,或者是后台 prohibited 模式。显然,通过看代码名称也明白了,原来这个后台模式,是故意不允许弹出窗口的。
显然,如果你声明程序是后台程序,那它的一切窗口都是不能获得焦点的,这个问题我一直以来以为是 macOS 的Bug.
那么,有没有别的方案呢?还真的有,除了上文的两种模式外,macOS 其实还提供了介于两者中间的模式,既像后台程序那样不显示图标,又能在必要的时候获取焦点和类似普通程序那样弹窗:
在必要的时候动态切换程序的运行模式为 accessory 即可。
当然,如果用代码太麻烦,我们也可以直接改 Info.plist,把 LSBackgroundOnly ,改为 LSUIElement ,即可。
No comments:
Post a Comment