FileProvider fails to trigger re-enumeration

I'm working on a FileProvider which allows access to encrypted files in Dropbox; I can successfully read and present the decrypted files, so I know it's basically working. But I'm having problems getting FileProvider to re-enumerate a folder when its encryption status changes.

When the FileProvider receives an update notification saying a folder is now encrypted, I use signalEnumerator to re-enumerate the folder:

FileProviderExtension.manager?.signalEnumerator(for: existingItem.itemIdentifier, completionHandler: { (ourError : Error?) -> Void in

      if let ourError = ourError {
          log("notifyCallback: mount / unmount failed re-enumeration: \(ourError)")
       } else {
          log("notifyCallback: mount / unmount signalled re-enumeration; pending")
       }
})

The log reports that the re-enumeration is pending... but as far as I can tell, neither enumerateItems nor enumerateChanges is called on the folder's item unless a Finder window is actually open for that folder. This means that, when an app other than Finder tries to access the files through the filesystem, it doesn't see the updated set of filenames.

(For further reference: I've added code to both enumerateItems and enumerateChanges, so that if the call has been triggered by a recent folder-encryption notification, it retrieves a complete set of items from the Dropbox folder. If a retrieved file has an encrypted filename, it reports it as a modified item and returns its filename in-clear; if the filename isn't encrypted, it doesn't return the item (for enumerateItems) or returns it as a deleted item (for enumerateChanges). This approach seems to work successfully for listing folders with a constant state; it's only if the user encrypts / decrypts a folder without currently having a Finder window open inside that folder that I'm not seeing a refresh.)

Any advice on how I can force a re-enumeration without a Finder window currently being displayed?

Replies

When using NSFileProviderReplicatedExtension, only call signalEnumerator with the .workingSet identifier (https://developer.apple.com/documentation/fileprovider/nsfileprovideritemidentifier/2879578-workingset). The system ignores other identifiers which are passed to the signalEnumerator method when using NSFileProviderReplicatedExtension.

When an item's metadata changes remotely, send the most up-to-date NSFileProviderItem on the working set, by signaling the working set and responding to the change enumeration request from the system. Once you complete the change enumeration on the working set, the remote changes will be propagated to disk by the system, and Finder's views will automatically update.

When using NSFileProviderReplicatedExtension, the working set must contain at least all of the items in the materialized set, plus the immediate children of any directories which are in the materialized set. (https://developer.apple.com/documentation/fileprovider/nsfileproviderreplicatedextension/3553308-materializeditemsdidchangewithco, https://developer.apple.com/documentation/fileprovider/nsfileprovidermanager/3181167-enumeratorformaterializeditems). Or, you can choose to populate the working set with every item in your remote database, rather than tracking the materialized set.

  • Hello @clenart. Thanks for your reply to clear some mysteries of NSFileProviderReplicatedExtension. I have some additional questions related this question , hoping you can help to provide some tips.

    When calling signalEnumerator with the .workingSet identifier. by observing, I notice that enumerateChanges of workingSet enumerator are called. The question what item should I pass to didUpdate or didDeleteItems. For example. when a new file F1 created in folder Dir1, should I update F1, Dir1 or both? Are there more detail documents that I can reference to?

    The second question is when will the system call currentSyncAnchor?

    Thank you.

    B.R.

    Jack

  • There is more documentation here: https://developer.apple.com/documentation/fileprovider/macos_support/synchronizing_the_file_provider_extension?language=objc

    To answer your specific example, if a new file F1 is created on the server inside Dir1, you should update both F1 and Dir1 via the working set.

    Update F1, because that is an item the system does not know about.

    Update Dir1, because the childItemCount property has changed.

    Regarding currentSyncAnchor, I couldn't find anything in the online documentation describing it. There is a detailed header comment describing when that method is called, in the FileProvider SDK header files. On -[NSFileProviderEnumerator currentSyncAnchorWithCompletionHandler:].

Add a Comment