objective-c – 如何将com.apple.systemuiserver首选项重新加载到SystemUIServer应用程序中?

对于我的Mac OSX应用程序,我有一个功能,当单击一个按钮时,它会删除屏幕右上角的系统时钟.控制显示哪些系统菜单的首选项(包括系统时钟)存储在〜/ Library / Preferences / com.apple.systemuiserver.plist中.我能够更新该文件中的相关首选项以删除系统时钟.但是,需要重新启动SystemUIServer应用程序,以便可以重新加载新的首选项并删除时钟.这是我用来重启SystemUIServer的代码.

NSTask *killSystemUITask = [[NSTask alloc] init];
NSMutableArray *args = [NSMutableArray array];
[args addObject:@"SystemUIServer"];
[killSystemUITask setLaunchPath:@"/usr/bin/killall"];
[killSystemUITask setArguments:args];
[killSystemUITask launch];

当SystemUIServer被杀死时,OSX会自动重启它.上面的代码有效,但系统时钟的删除并不像我想的那样干净.整个系统栏将被删除一秒钟.有人能想出更好的方法将首选项重新加载到SystemUIServer中吗?理想情况下,我希望系统时钟的移除与日期和时间中的时钟显示功能一样干净.系统首选项应用程序的时间首选项.

最佳答案 您是否考虑过使用AppleEvents / OSAScript尝试驱动pref窗格?虽然Network prefs窗格似乎是唯一具有完全内置可编写脚本的窗格,但您可以使用System Events驱动任何UI.在AppleScript中进行原型设计很容易.这是我想出的:

tell application "System Preferences"
    reveal pane "Date & Time"
    reveal anchor "ClockPref" of pane "Date & Time"
    tell application "System Events"            
        tell tab group 1 of window 1 of process "System Preferences"
            repeat with cbIndex from 0 to count of checkboxes
                tell checkbox cbIndex
                    if title contains "menu bar" then
                        click
                        exit repeat
                    end if
                end tell
            end repeat
        end tell
    end tell
    quit
end tell

你可以通过使用NSAppleScript对象来原样使用它,或者如果你感觉自虐,你可以深入研究找出正确的AppleEvents发送的细节. (我建议使用前一种方法来保持理智,但后者在运行时会执行得更快.)

优点:简单.

缺点:启动系统首选项(可以看到在Dock中弹跳),需要启用“启用辅助设备访问”(像许多其他东西一样)

很难说杀死SystemUIServer在视觉上是好还是坏,但它几乎肯定对可能与SystemUIServer交互的任何其他组件更友好.

至于摆脱码头弹跳,这个question over here提到如何在没有停靠图标的情况下启动.对此我可以补充一点,在过去,我已经遇到了这个问题,而我提出的解决方案是,在高层次上,这个:

>获取唯一/安全的临时目录
>制作一个仅有硬链接的应用程序整个捆绑镜像(pax -rwl将有助于此)
>将硬链接的Info.plist替换为Info.plist的真实副本
>根据其他问题中的指示编辑副本. (注意:除了在这里设置NSUIElement = true之外还有其他选项,但我将这些作为练习留给读者和谷歌.)
>使用临时目录中的应用程序
>删除临时目录.

在尝试驱动第三方应用程序时,这种方法对我来说非常强大.我猜你将来可能遇到签名/沙盒化系统应用程序的问题. (即更改他们的Info.plist会更改签名,他们可能会拒绝运行.)此外,当然,任何沙盒应用程序都需要特定的权利或例外才能发送AppleEvent,但我猜这对于杀死系统进程也是如此(如果甚至可以从沙盒应用程序中做到这一点.)

最后,如果您认为重要,您应该file a bug report with Apple请求一流的API或脚本.

点赞