Add Application to Dock – Cocoa NSApplication Category
The need to quickly add my application to a user’s Dock arose while working on a project for a client a few months back. I was intrigued by the code (first encounter with NSAppleScript as the big one) and took some time to sit down and refine what I had originally pieced together into something more usable.
What I eventually settled upon was writing a few category methods for NSApplication, allowing you to easily check and see if your app is already in the user’s Dock, or add your application to the users Dock (doesn’t allow for precise placement).
NSApplication-MacFanatic.h adds the following 4 methods:
@interface NSApplication (MacFanatic) - (BOOL)addApplicationToDock; - (BOOL)applicationExistsInDock; - (BOOL)addApplicationToDock:(NSString*)path; - (BOOL)applicationExistsInDock:(NSString*)path; @end
Examples
To quickly see if your application is in the user’s Dock:
if ( [[NSApplication sharedApplication] applicationExistsInDock] ) { // App is in dock }
To quickly add your application to the user’s Dock:
[[NSApplication sharedApplication] addApplicationToDock];
These first two methods should undoubtedly come in handy, but as I was originally writing an installer and needed to add the application I was installing, not the currently running application (the installer), to the Dock, so there are yet two more methods for checking a specific application by passing a path.
Checking to see if Atlas is in the user’s Dock:
if ( [[NSApplication sharedApplication] applicationExistsInDock:@"/Applications/Atlas.app"] ) { // Atlas is in dock }
Adding Atlas to the user’s Dock:
[[NSApplication sharedApplication] addApplicationToDock:@"/Applications/Atlas.app"];
Inner Workings
Here’s a quick peak at the method for determining if the application is currently in the user’s Dock:
44 45 46 | - (BOOL) applicationExistsInDock { return [self applicationExistsInDock:[[NSBundle mainBundle] bundlePath]]; } |
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 | - (BOOL) applicationExistsInDock:(NSString*)path { NSString* app = nil; NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; [defaults addSuiteNamed:@"com.apple.Dock"]; NSArray* apps = [defaults objectForKey:@"persistent-apps"]; for ( NSDictionary* d in apps ) { app = [[[d objectForKey:@"tile-data"] objectForKey:@"file-data"] objectForKey:@"_CFURLString"]; if ( [app isEqualToString:path] ) { return YES; } } return NO; } |
Some Notes
All of these methods are based on absolute paths – not application identifiers. So if the user is running your application from the Desktop and has an alias to your application in the /Applications folder, it will return false. Doesn’t matter that the user has two copies of your application.
Love to get some feedback on this, it’s my finest code contribution on the blog to date I believe. I’ve refined this a good bit, but it could use some more love I’m sure. I hope to hear that someone has used this in a project!
Updates
This was marked as Tiger compatible code, but I noticed I’m using Fast Iteration, which was introduced in Leopard. For Tiger compatibility, just change a few lines:
93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 | - (BOOL) applicationExistsInDock:(NSString*)path { NSString* app = nil; NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults]; [defaults addSuiteNamed:@"com.apple.Dock"]; NSArray* apps = [defaults objectForKey:@"persistent-apps"]; NSDictionary* d = nil; NSEnumerator* e = [apps objectEnumerator]; while ( d = [e nextObject] ) { app = [[[d objectForKey:@"tile-data"] objectForKey:@"file-data"] objectForKey:@"_CFURLString"]; if ( [app isEqualToString:path] ) { return YES; } } return NO; } |
The download has been updated to contain the new code.
Downloads
Grab the .h and .m files in this zip (10.4+)
Example Xcode project (Xcode 3.2, 10.6+)














Submitting Your Comment, give me a second...