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

标签 objective-c cocoa macos nstask

对于我的 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 pane 本身?虽然网络首选项 Pane 似乎是唯一具有完全内置脚本的 Pane ,但您可以使用系统事件驱动任何 UI。在 AppleScript 中制作原型(prototype)非常容易。这是我想出的:

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提到如何在没有停靠栏图标的情况下启动。对此我可以补充一点,在过去,我一直在为这个问题争论不休,而我想出的解决方案在高层次上是这样的:

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

在尝试驱动 3rd 方应用程序时,这种方法对我来说非常可靠。我猜你将来可能会遇到签名/沙盒系统应用程序的问题。 (即更改他们的 Info.plist 会更改签名,他们可能会拒绝运行。)而且,自然地,任何沙盒应用程序都需要特定的权利或异常(exception)才能发送 AppleEvents,但我想这也是杀死系统进程的真实情况(如果这甚至可以从沙盒应用程序中完成的话。)

最后,你应该 file a bug report with Apple如果您认为这很重要,请为此请求一流的 API 或脚本能力。

关于objective-c - 如何将 com.apple.systemuiserver 首选项重新加载到 SystemUIServer 应用程序中?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/5143117/

相关文章:

objective-c - 直接访问 ivars 与使用访问器有何不同?

ios - 单击主视图 Controller 中的按钮以将录制的视频保存在容器 View 中?

objective-c - 在 NSImage 中用另一种颜色替换一种颜色

Objective-C 静音和取消静音的方法

bash - 如果 #channels 为 2,则连接 wav 文件将忽略

python套接字,无效参数

macos - 在 OS X 中,什么是 BASE 图形绘制层?

objective-c - UIBezierPath 多线条颜色

ios - 为什么在 Storyboard 中设置标签栏项目标题和图像有时不起作用?

cocoa - 在 cocoa 应用程序中预定义全局热键和键盘布局