Question

I'm searching for a solution to do File icon overlays (icon badging) (like Dropbox does it on mac) with cocoa on Mac.

Does anyone knows a way to do this?

I've searched the Xcode docs and looked into scpplugins source code which is kind of old carbon code.

Was it helpful?

Solution

Since the Finder was reworked in Snow Leopard, the older Carbon methods will no longer work. The route I've taken to be able to badge icons in Finder involves writing a custom bundle which then needs to be injected into the Finder.

Look into Wolf Rentzsch's mach_inject (https://github.com/rentzsch/mach_star/tree/master/mach_inject) to be able to inject a custom bundle to a Cocoa application.

Use class-dump to be able to get a look into the header files of a Cocoa application (such as the Finder in Snow Leopard and Lion) to get an idea of what you will need to override in your own bundle.

OTHER TIPS

A litte bit late, but maybe will be help someone.

I solved same problem with class NSWorkspace (see setIcon:forFile:options)

Basic idea:

  1. Try to get preview of file with QLThumbnailImageCreate (if not NULL you will get thumbnail icon)

  2. If you didn't get thumbnail, then get default OS X icon for file (NSWorkspace iconForFile)

  3. Combine thumbnail (or default icon) with your badge

  4. Set new icon to the file (NSWorkspace setIcon:forFile:options)

I know this is an old question.

In recent time there is a library that implement this functionality: https://github.com/liferay/liferay-nativity.

NSDockTile makes this very simple:

NSDockTile *dockTile = [NSApp dockTile];
[dockTile setBadgeLabel:@"33"];

You can use the following two methods to have icon overlay over the folders/files.

  1. You can use -setIcon:forFile:options: method on NSWorkspace if you want to change the icon of a file or folder in Mac OS X.
    However after you apply icon overlay using this method, overlay exits even though you moved that file/folder outside. This may not be the exact solution.

  2. Instead use the Finder Sync Extension target (File - New - Target - Finder Sync Extension) inside your app.
    Once you created the extension, your application doesn't have direct communication with this target. In order to activate, use AppleScript command (I don't think there is a better alternative for this.)

To activate

NSString *pluginPath = [[[NSBundle mainBundle] builtInPlugInsPath] stringByAppendingPathComponent:@"yourextension.appex"];

NSString *pluginkitString = [NSString stringWithFormat:@"pluginkit -e use -a \"%@\"", pluginPath];
system([pluginkitString cStringUsingEncoding:NSUTF8StringEncoding]);

Once target activated, there are couple of ways were our application can communicate with that extension. Few of them are:

Using NSDistributedNotificationCenter. This class provides a way to send notifications to objects in other tasks(like the extension here).

Other way is to use:

[[NSUserDefaults alloc] initWithSuiteName:@"teamid.com.company.test"];

Both your application and the target should have common group identifier(i.e "teamid.com.company.test").

For this enable "App Groups" under Target - Capabilities - App Groups and give the identifier like the above (i.e"teamid.com.company.test") were teamid is the id that you will get it from your apple developer portal. Do the same steps for your Extension target as well.

Before to conclude, be sure that extension is activated or not. To check that go to System Preference - Extensions - Your App Finder. This is the global point were user can enable/disable icon overlay for your application.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top