How can I change the Dock preferences programmatically?
I'm 开发者_StackOverflow中文版new to Cocoa/macOS programming. I just found out that NSUserDefaults
can be used to change application/system settings, like the way the defaults
command does.
But I don't know how to cause these settings to update.
e.g., I use NSUserDefaults
to set the dock size to 32, and synchronize the setting. But the dock retains the old setting.
Even when I use defaults write com.apple.dock tilesize 32
to change its size, it won't be updated until I logout and login.
Is there any other technology to notify the dock to get the update? I know that System Preferences can do that.
Thank you!
The Mac OS X dock doesn't reload its settings until it is killed and restarted. In the same way that you'd have to change its settings manually via the terminal (defaults write com.apple.dock tilesize 32; killall Dock
), you have to do that in code. So, while you've written the defaults
portion of the code, you have to write the kill
portion:
NSRunningApplication *dock = [NSRunningApplication runningApplicationWithBundleIdentifier:@"com.apple.dock"];
[dock terminate];
If you want to do this without killing the dock, sorry, but you're out of luck. While there might be a hidden API to force the dock to reload its settings on the fly, in all my searching I have never found any hints of how one can do this (there are no notifications posted on the hidden distributed notification center that most applications to interact with one another).
With the magic of the Xcode debugger and some formatted disassembly, I've created this short header file you can paste into your code (GitHub gist is here). Function names are hopefully self-explanatory.
// TO USE THESE INTERFACES, you MUST link against ApplicationServices.framework.
#pragma once
#ifdef __cplusplus
extern "C" {
#endif
// Boolean preferences
extern void CoreDockSetLaunchAnimationsEnabled(bool enable);
extern void CoreDockSetMagnificationEnabled(bool enable);
extern void CoreDockSetAutoHideEnabled(bool enable);
extern void CoreDockSetMinimizeInPlace(bool enable);
// Sets other preferences such as whether the indicators below the app icons are shown
// 'preferenceDict' is a CFDictionary containing a magic key value
// Will require further inspection of Dock.prefpane to find all the keys
// (I haven't noted them down)
extern void CoreDockSetPreferences(CFDictionaryRef preferenceDict);
#ifdef __cplusplus
} // extern "C"
#endif
Preferences updated in this way are reflected instantaneously, because these functions actually messagethe "com.apple.dock" mach service internally.
Have fun!
PLEASE NOTE: These are private system APIs. Any apps submitted to the Mac App Store that use these APIs will be rejected. On another note, if you have no App Store intentions, there's no harm in using these interfaces. They appear to have existed since the very dawn of Mac OS X, and it's highly improbable they'll be disappearing in the near future, if ever.
You can use AppleScript to set some of the properties of the dock by scripting System Preferences, you may want to take a look at seeing if you can take that approach instead? Maybe call some AppleScript from your app?
精彩评论