4

对于我的 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 的更好方法?理想情况下,我希望系统时钟的删除与系统偏好设置应用程序的日期和时间偏好中的时钟显示功能一样干净。

4

1 回答 1

2

您是否考虑过尝试使用 AppleEvents/OSAScript 驱动偏好窗格本身?虽然 Network prefs 窗格似乎是唯一具有完全内置脚本功能的窗格,但您可以使用系统事件驱动任何 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 交互的任何其他组件更友好。

至于摆脱停靠弹跳,这里的这个问题提到了如何让事情在没有停靠图标的情况下启动。为此,我可以补充一点,在过去,我曾为这个问题争论过,我想出的解决方案在高层次上是这样的:

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

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

最后,如果您认为这很重要,您应该向 Apple 提交一份错误报告,要求提供一流的 API 或脚本能力。

于 2011-12-28T15:38:12.113 回答