Thanks for being a part of WWDC25!

How did we do? We’d love to know your thoughts on this year’s conference. Take the survey here

Seeking a Reliable Way to Refresh Finder for Custom Folder Icon Changes in a Sandboxed App

Hello everyone,

I'm developing a macOS application that programmatically sets custom icons for folders, and I've hit a wall trying to get Finder to display the icon changes consistently.

The Goal: To change a folder's icon using NSWorkspace.shared.setIcon and have Finder immediately show the new icon.

What I've Tried (The Refresh Mechanism):

After setting the icon, I attempt to force a Finder refresh using several sandbox-friendly techniques:

  • Updating the Modification Date (the "touch" method):

    try FileManager.default.setAttributes([.modificationDate: Date()], ofItemAtPath: pathToUse)
    
  • Notifying NSWorkspace:

    NSWorkspace.shared.noteFileSystemChanged(pathToUse)
    
  • Posting Distributed Notifications:

    DistributedNotificationCenter.default().post(name: Notification.Name("com.apple.Finder.FolderChanged"), object: pathToUse)
    

The Problem:

This combination of methods works perfectly, but only under specific conditions:

  1. When setting a custom icon on a folder for the first time.
  2. When changing the icon of an alias.

For any subsequent icon change on a regular folder, Finder stubbornly displays the old, cached icon. I've confirmed that the user can see the new icon by manually closing and reopening the folder window, but this is obviously not a user-friendly solution.

Investigating a Reset with AppleScript:

I've noticed that the AppleScript update command seems to force the kind of complete refresh I need:

tell application "Finder"
    update POSIX file "/path/to/your/folder"
end tell

Running this seems to reset the folder's state in Finder, effectively recreating the "first-time set" scenario where my other methods work.

However, the major roadblock is that I can't figure out how to reliably execute this from a sandboxed environment. I understand it likely requires specific scripting entitlements, but it's unclear which ones would be needed for this update command on a user-chosen folder, or if it's even permissible for the App Store.

My Questions:

  1. Is there a reliable, sandbox-safe way to make the standard Cocoa methods (noteFileSystemChanged, updating the modification date, etc.) work for subsequent icon updates on regular folders? Am I missing a step?

  2. If not, what is the correct way to configure a sandboxed app's entitlements to safely run the tell application "Finder" to update command for a folder the user has granted access to?

Any insight or alternative approaches would be greatly appreciated. Thank you

Answered by DTS Engineer in 844055022

I've noticed that the AppleScript update command seems to force the kind of complete refresh I need:

So, what this actually does is technically documented, though the source is more than a little obscure. From the Files.h header doc for the long deprecated "FNNotify" API:


 *  Discussion:
 *    FNNotify is used to notify system clients (such as the Finder) of
 *    modifications to the contents of a directory, specifically
 *    addition or removal of files or folders from the directory. The
 *    Finder and other system clients will refresh their views of the
 *    specified directory when they receive the change notification.
 *    FNNotify is not meant to notify the Finder of changes to a
 *    specific file (for example, changes to a file's type or creator);
 *    for that purpose, use a kAESync AppleEvent sent to the Finder.

kAESync is defined in the equally obscure "FinderRegistry.h", inside the Carbon framework:

/*
   The old Finder Event suite was 'FNDR'
   The new suite is 'fndr'
*/
enum {
  kAEFinderSuite                = 'fndr'
};

/*
  //////////////////////////////////////
   Finder Events
  //////////////////////////////////////
*/
enum {
  kAECleanUp                    = 'fclu',
  kAEEject                      = 'ejct',
  kAEEmpty                      = 'empt',
  kAEErase                      = 'fera',
  kAEGestalt                    = 'gstl',
  kAEPutAway                    = 'ptwy',
  kAERebuildDesktopDB           = 'rddb',
  kAESync                       = 'fupd',
  kAEInterceptOpen              = 'fopn'
};

SO, that's the event you need to send. That leads to here:

However, the major roadblock is that I can't figure out how to reliably execute this from a sandboxed environment. I understand it likely requires specific scripting entitlements, but it's unclear which ones would be needed for this update command on a user-chosen folder, or if it's even permissible for the App Store.

What have you actually tried here? I haven't tested this in any detail but, as far as I can tell, kAEFinderSuite/kAESync is one of the "safe" AppleEvent that your app should be allowed to send without any additional configuration.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

I've noticed that the AppleScript update command seems to force the kind of complete refresh I need:

So, what this actually does is technically documented, though the source is more than a little obscure. From the Files.h header doc for the long deprecated "FNNotify" API:


 *  Discussion:
 *    FNNotify is used to notify system clients (such as the Finder) of
 *    modifications to the contents of a directory, specifically
 *    addition or removal of files or folders from the directory. The
 *    Finder and other system clients will refresh their views of the
 *    specified directory when they receive the change notification.
 *    FNNotify is not meant to notify the Finder of changes to a
 *    specific file (for example, changes to a file's type or creator);
 *    for that purpose, use a kAESync AppleEvent sent to the Finder.

kAESync is defined in the equally obscure "FinderRegistry.h", inside the Carbon framework:

/*
   The old Finder Event suite was 'FNDR'
   The new suite is 'fndr'
*/
enum {
  kAEFinderSuite                = 'fndr'
};

/*
  //////////////////////////////////////
   Finder Events
  //////////////////////////////////////
*/
enum {
  kAECleanUp                    = 'fclu',
  kAEEject                      = 'ejct',
  kAEEmpty                      = 'empt',
  kAEErase                      = 'fera',
  kAEGestalt                    = 'gstl',
  kAEPutAway                    = 'ptwy',
  kAERebuildDesktopDB           = 'rddb',
  kAESync                       = 'fupd',
  kAEInterceptOpen              = 'fopn'
};

SO, that's the event you need to send. That leads to here:

However, the major roadblock is that I can't figure out how to reliably execute this from a sandboxed environment. I understand it likely requires specific scripting entitlements, but it's unclear which ones would be needed for this update command on a user-chosen folder, or if it's even permissible for the App Store.

What have you actually tried here? I haven't tested this in any detail but, as far as I can tell, kAEFinderSuite/kAESync is one of the "safe" AppleEvent that your app should be allowed to send without any additional configuration.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Seeking a Reliable Way to Refresh Finder for Custom Folder Icon Changes in a Sandboxed App
 
 
Q