How does Numbers.app detect that a document was moved to Recently Deleted, and can third-party apps implement the same behavior?

The Numbers.app reopens the last edited document when the app launches. If the document was moved to another folder in the Files.app while the app was not running, Numbers.app correctly tracks the file and reopens it. However, if the document was deleted in the Files.app and moved to Recently Deleted, Numbers.app does not reopen the document when the app launches.

Question :

  1. How does Numbers.app detect that a document has been moved to Recently Deleted?
  2. Can third-party apps implement the same behavior?

What I tested :

If a file is moved while the app is not running, resolving a bookmark successfully tracks the moved file. Files that are deleted via the Files.app appear in Recently Deleted, but those files are actually moved to the following directories:

iCloud Drive /var/mobile/Library/Mobile Documents/.Trash/

On My iPad /var/mobile/Containers/Shared/AppGroup/{UUID}/File Provider Storage/.Trash/

App sandbox Documents directory ([On My iPad]/[Any App]) /var/mobile/Containers/Data/Application/{UUID}/Documents/.Trash/

When resolving the bookmark after deletion, the bookmark still resolves successfully and returns the new file URL inside the .Trash directory.

I tried the following checks on the resolved URL:

All of these behaved the same as when the file was moved to a normal directory. None of these checks allowed me to detect that the file had been deleted.

Additional experiment:

I suspected that the app might simply check whether the path contains ".Trash", so I performed the following experiment.

If a .numbers file is moved to

  • /var/mobile/Containers/Data/Application/{UUID}/Documents/.Trash/

then

  • The file appears in Recently Deleted in Files.app
  • Numbers.app does not reopen the document when the app launches

However, if the same file is moved to

  • Documents/Trash
  • Documents/.Trashed
  • Documents/Any Folder/.Trash

then

  • The file does not appear in Recently Deleted in Files
  • Numbers does reopen the document when launched

This suggests that Numbers.app is not simply checking whether the path contains ".Trash".

Answered by DTS Engineer in 879890022
  1. How does Numbers.app detect that a document has been moved to Recently Deleted?
  2. Can third-party apps implement the same behavior?

In my reply on the other thread, I said this:

"I haven't looked at it in detail, but I suspect it's using a combination of security-scoped bookmark (for "basic" file tracking on the device) and the iCloud Document API. In particular, the key "NSMetadataQueryUpdateRemovedItemsKey" should be included in the "NSMetadataQueryDidUpdateNotification" you receive for deleted files."

Have you tested this? As I'm fairly sure that's what Numbers is doing.

One follow-up comment on this point from your other thread:

Result: The file disappears from Files App Recently Deleted. In contrast, using [NSFileManager replaceItemAtURL:withItemAtURL:] keeps the file visible in Recently Deleted. Is this difference designed behavior?

In the context of iCloud, delete/move and replaceItemAtURL are fundamentally different operations. In the first case, you deleted an existing file "record", then moved a different file record into the location of the previous file record. By contrast, "replaceItemAtURL" is updating the "record" of the existing file.

That also explains the difference in deletion behavior, as file provider deletion state is a characteristic of the object "record" itself, not necessarily its location. Also, and I should have mentioned this in my previous reply, make sure you're using file coordination for all of this.

Having said all that...

I suspected that the app might simply check whether the path contains ".Trash", so I performed the following experiment.

...I also don't really see any downside with using this as an additional check, particularly as an initial "screen" alongside the metadata queries. While it's true that these checks won't exactly match the system’s view in Files.app, in practice I don't think that will really matter.

The issue here is real user behavior. That is, what user would:

  1. Create a ".Trash" directory in a non-standard location.

  2. Choose to store files in that location.

  3. Be "upset" when your app warned them that those files were "in the trash".

The first two are unlikely to happen and I can't see any user experienced enough to create that state then getting upset about #3.

[1] In theory, iCloud Drive is simply one implementation of the more "general" file provider architecture. The fact that iCloud Drive uses specific directories to store deleted files doesn't mean all file providers will.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

It's not really about what the Numbers guy does but probably what FileDocument lets it do it. I have never used FileDocument with an iOS app. I do have a macOS application with FileDocument. If I open and then close a document and then move it under a different volume or a folder, the application is still able to open it. But it won't if I move a file to the dumpster.

  1. How does Numbers.app detect that a document has been moved to Recently Deleted?
  2. Can third-party apps implement the same behavior?

In my reply on the other thread, I said this:

"I haven't looked at it in detail, but I suspect it's using a combination of security-scoped bookmark (for "basic" file tracking on the device) and the iCloud Document API. In particular, the key "NSMetadataQueryUpdateRemovedItemsKey" should be included in the "NSMetadataQueryDidUpdateNotification" you receive for deleted files."

Have you tested this? As I'm fairly sure that's what Numbers is doing.

One follow-up comment on this point from your other thread:

Result: The file disappears from Files App Recently Deleted. In contrast, using [NSFileManager replaceItemAtURL:withItemAtURL:] keeps the file visible in Recently Deleted. Is this difference designed behavior?

In the context of iCloud, delete/move and replaceItemAtURL are fundamentally different operations. In the first case, you deleted an existing file "record", then moved a different file record into the location of the previous file record. By contrast, "replaceItemAtURL" is updating the "record" of the existing file.

That also explains the difference in deletion behavior, as file provider deletion state is a characteristic of the object "record" itself, not necessarily its location. Also, and I should have mentioned this in my previous reply, make sure you're using file coordination for all of this.

Having said all that...

I suspected that the app might simply check whether the path contains ".Trash", so I performed the following experiment.

...I also don't really see any downside with using this as an additional check, particularly as an initial "screen" alongside the metadata queries. While it's true that these checks won't exactly match the system’s view in Files.app, in practice I don't think that will really matter.

The issue here is real user behavior. That is, what user would:

  1. Create a ".Trash" directory in a non-standard location.

  2. Choose to store files in that location.

  3. Be "upset" when your app warned them that those files were "in the trash".

The first two are unlikely to happen and I can't see any user experienced enough to create that state then getting upset about #3.

[1] In theory, iCloud Drive is simply one implementation of the more "general" file provider architecture. The fact that iCloud Drive uses specific directories to store deleted files doesn't mean all file providers will.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

How does Numbers.app detect that a document was moved to Recently Deleted, and can third-party apps implement the same behavior?
 
 
Q