Write access with URL.startAccessingSecurityScopedResource

In my App I want to create a new directory structure in a user selected base directory. In the entitlements com.apple.security.files.user-selected.read-write = true is defined. I call URL.startAccessingSecurityScopedResource( ) and get a true value back. When calling FileManager.createDirectory( at: directoryURL, withIntermediateDirectories: true, attributes: nil ) an error is thrown that write access is missing. User has write permissions in that directory. When the user selects a directory I store a bookmark via an @AppStorage variable. After write attempt URL.stopAccessingSecurityScopedResource() is called. I have also implemented a SharedExtension (especially for the Photo app). When user calls the SharedExtension of my app and the app just uses the bookmark stored with @AppStorage and follows the same process as described above no difficulties appear and directories are created as expected. Changing back to the main app, using again the untouched bookmark and execute the exactly same code as in the first attempt everything works fine and as expected. The phenomenon appears on real devices but not on simulator. Any ideas how to solve the issue of having no write access in first attempt?

So, let me start here:

The phenomenon appears on real devices but not on simulator.

What's the target device you're actually running on? macOS handles files VERY differently than other platforms, completely changing the dynamics of these issues.

That leads to here:

In my App I want to create a new directory structure in a user selected base directory.

Where is the user selected directory you're working with located?

Outside of macOS, bookmark resolution to external volumes across mounts (r.102995804) is broken, which can create exactly the kind of problem you're describing. That is, the bookmark works fine for "awhile" (because the volume is still mounted) then breaks "later" when the volume is unmounted and then remounted.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi Kevin, thanks a lot for your investigation. That's really appreciated. To your questions:

What's the target device you're actually running on?

Target devices are iOS and iPadOS devices with iOS 18.0 and higher. Tests have been performed on iPhone 15 and 16 and iPad.

Where is the user selected directory you're working with located?

Difficulties appear with network located directories as well as with local ones.

While fighting with the issue I also tried not to store the bookmark but the URL with no change in the behavior.

Difficulties appear with network located directories as well as with local ones.

While fighting with the issue I also tried not to store the bookmark but the URL with no change in the behavior.

So, let me state the situation a bit more clearly. Given the current state of the system (primarily due to r.102995804), currently:

  1. There isn't ANY reliable way for an app to reference a file system object outside of it's own containers. Your app doesn't have any way to control or determine "where" external files come from, which means your app has to "plan" on any reference breaking. You can try and use bookmarks to preserve access but you can't assume they'll be reliable.

  2. When saving references to file inside your own containers (meaning your apps own container, shred containers, etc.), those references need to be saved relative to the container directory and not as fixed URLs or bookmarks. Containers can and will move with will break URLS and could break bookmarks. The difference (vs. #1) is that your app has the ability to "find" it's own containers again, allowing you to find the files again through a relative references.

__
Kevin Elliott
DTS Engineer, CoreOS/Hardware

Hi Kevin, thanks again for all your inputs. My difficulty was that initially I got a fault when trying to create subdirectories in a user selected directory. All the stuff with bookmarks etc. was later on and "solved" in some way the accessing issue. I played around and found a way to be able to write to the directory right from the beginning. When I removed the entry for Hardened Runtime in the project settings I was able to create the subdirectories with the first attempt.

Write access with URL.startAccessingSecurityScopedResource
 
 
Q