Post

Replies

Boosts

Views

Activity

Reply to iOS folder bookmarks
It was: Error Domain=NSCocoaErrorDomain Code=256 "Could not open() the item" but then I look in the console: error 00:47:00.954979+0100 kernel Sandbox: BookmarksBench(61956) deny(1) file-write-data /Users/user/Documents/file which reminded me to check the entitlements – turns out I forgot to specify read/write access for user selected files... Fixed that - and everything is good now. Thank you. PS. Quite interesting that that affects secure bookmark creation, but not normal bookmark creation..
Topic: App & System Services SubTopic: Core OS Tags:
Sep ’25
Reply to iOS folder bookmarks
Thank you Kevin, My question at this point is whether there's this other bug on macOS worth filing that when creating a bookmark with "withSecurityScope=on" option I'm getting an error. Very easy to demonstrate using my test bench.
Topic: App & System Services SubTopic: Core OS Tags:
Sep ’25
Reply to iOS folder bookmarks
[quote='856443022, DTS Engineer, /thread/797469?answerId=856443022#856443022'] You're testing on iOS, not macOS [/quote] In fact, that was on macOS... Your app never created a security-scoped bookmark Well, the bench UI is flexible, it's a matter of selecting that checkbox in the bench UI.. However, now that I tried it (on Mac) - the create bookmark fails with error.. "NSCocoaErrorDomain Code=256 "Could not open() the item", specifically this very first step (after the picker): Create with NSURL.BookmarkCreationOptions.withSecurityScope. However, security scoped creation fails at #3. Yep, for me it's failing on 4. tap "Create bookmark" - if I select "withSecurityScope (Mac only)" in the UI.
Topic: App & System Services SubTopic: Core OS Tags:
Sep ’25
Reply to Selecting "On My iPhone" folder in Files
Please see the code attached here.. Normally when you get a URL to a file outside your sandbox, the URL is only valid until the delegate method returns That's not what I experience using the test app - it merely remembers the url in a variable and immediately returns from the delegate method, at some later point you could tap "start access" and afterwards "read" or "make bookmark", etc. this machinery itself works correctly. If I were to guess: iOS doesn't want us to have an access to all app's documents (e.g. for privacy)... It's just having a possibility to select that root level makes things confusing.
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
First off, as a clarification, "withoutImplicitStartAccessing" does NOT mean "don't call startAccessingSecurityScopedResource" for me. It feels you are talking here about withoutImplicitSecurityStore creation option instead of withoutImplicitStartAccessing resolving option.. In my tests withoutImplicitStartAccessing does pretty much what is says on the tin. For example: create a bookmark (without specifying neither withoutImplicitSecurityStore nor withSecurityScope persist it somehow (the above test app writes it to user defaults) restart the app resolve bookmark specifying withoutImplicitStartAccessing access the url - that would fail. call startAccessingSecurityScopedResource on it - it returns true access the url again - that will now work if instead of 4 above you resolve the bookmark without specifying withoutImplicitStartAccessing, then access the url - that would work right away. Behind the scenes, what actually happens when you resolve a bookmark is Thanks a lot for those details, it's really helpful to see how it works behind the scenes. For example, one solution would be to allow the app to push "back" to Files.app*, providing the same functionality as "Show in Finder". In any case, please file a bug on this and post the bug number back here. *Strictly speaking, this is doable today, but the URL scheme is not documented, so it shouldn't be used. You mean it's doable to get the app name from the Application/2A6A7975-6CE1-40F0-B7D0-18A6E64C0D89/ url via some undocumented means? Filed the radars: FB19996364 - "iOS and macOS: bookmarkData expected to fail but it doesn't" FB19995901 - "iOS: The app name returned from file/folder picker API is cryptic" FB19995978: "iOS: I could select "On My iPhone" folder in Files.app for the issue discussed in another thread
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
Also, to be clear, using "withoutImplicitStartAccessing" is EXCEEDINGLY rare, even within the system. I can't think of any reason why an app would do this, as you're essentially asking the system to give you a URL you can't use. There must be some reason... otherwise we wouldn't have withoutImplicitStartAccessing in the first place ;) FWIW iOS UIDocumentPickerViewController provides you an URL for with startAccessingSecurityScopedResource has not been called yet.. I guess this is another difference between the two platforms. Please file a bug Will do shortly. returning the app name has privacy implications But so should be the case on macOS, no? import SwiftUI struct ContentView: View { var body: some View { let view = Button("Pick Folder") { #if os(macOS) macPickFolder() #else phoneShowPicker = true #endif } .buttonStyle(.borderedProminent) #if os(macOS) return view #else return view.sheet(isPresented: $phoneShowPicker) { PhoneFilePicker(isFolder: true) { url in if let url { printUrl(url) } } } #endif } #if os(macOS) func macPickFolder() { let panel = NSOpenPanel() panel.directoryURL = URL.libraryDirectory.appendingPathComponent("Containers") panel.allowsMultipleSelection = false panel.canChooseDirectories = true panel.canChooseFiles = true panel.allowedContentTypes = [.folder] if panel.runModal() == .OK { if let url = panel.url { printUrl(url) } } } #else @State private var phoneShowPicker = false #endif func printUrl(_ url: URL) { // NOTE: on mac it's possible to select the app container itself // and on iOS it is not, you could only select the "Documents" folder inside // making the test consistent, so that even on macOS if you select "Data" // inside the app container it will work the same way as on iOS. var url = url if (url.lastPathComponent == "Data") || (url.lastPathComponent == "Documents") { url = url.deletingLastPathComponent() } let result = url.startAccessingSecurityScopedResource() print("startAccessingSecurityScopedResource result:", result) defer { url.stopAccessingSecurityScopedResource() } let values = try! url.resourceValues(forKeys: [.nameKey, .localizedNameKey]) print("url:", url) print("name:", values.name ?? "nil") print("localizedName:", values.localizedName ?? "nil") } } #Preview { ContentView() } #if !os(macOS) struct PhoneFilePicker: UIViewControllerRepresentable { let isFolder: Bool var onPick: (URL?) -> Void func makeUIViewController(context: Context) -> UIDocumentPickerViewController { let picker = UIDocumentPickerViewController(forOpeningContentTypes: [isFolder ? .folder : .item], asCopy: false) picker.delegate = context.coordinator picker.allowsMultipleSelection = false return picker } func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: Context) {} func makeCoordinator() -> Coordinator { Coordinator(onPick: onPick) } class Coordinator: NSObject, UIDocumentPickerDelegate { var onPick: (URL?) -> Void init(onPick: @escaping (URL?) -> Void) { self.onPick = onPick } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { onPick(urls.first!) } func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) { onPick(nil) } } } #endif @main struct TestApp: App { var body: some Scene { WindowGroup { ContentView() } } } Example output on macOS: url: file:///Users/user/Library/Containers/com.apple.AboutThisMacLauncher/ name: com.apple.AboutThisMacLauncher localizedName: About This Mac on iOS: url: file:///private/var/mobile/Containers/Data/Application/2A6A7975-6CE1-40F0-B7D0-18A6E64C0D89/ name: 2A6A7975-6CE1-40F0-B7D0-18A6E64C0D89 localizedName: 2A6A7975-6CE1-40F0-B7D0-18A6E64C0D89 Are you starting from a document? You should be able to get the UTI of a document. If you ask for the localizedDescription, that might be what you're looking for. Etresoft, I am not sure I follow, please explain. PS. I'm not sure if this is important or not: compared to mac where I could select the container folder itself on iPhone I could only select the Documents folder inside... - the "File" UI just works that way... Which means I have to deleteLastPathComponent to get to the app URL... but that URL was not exactly the one user gave permission for.. Maybe because of that localizedName doesn't work? (despite it works on Mac after stripping the trailing "Data" off the url, but at this point I'd be not surprised if that's yet another difference between the platforms).
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
It's long been documented Specifically is it documented that we need to call stopAccessingSecurityScopedResource after resolvingBookmarkData that has no withoutImplicitStartAccessing in the options? More to the point, the APIs involved here are part of a LONG chain of evolution that keeps being expanded/tweaked/repurposed ... Thanks for those details. Try both displayName(atPath:) (on the parent directories) and componentsToDisplay(forPath:). These do some basic substitutions: /private/var/mobile -> "User" /private/var/ -> "System"+"var" /private/ -> "System"+"private" / -> "System" but UUID is not converted: ... /Application/29CC76B4-074B-43CC-87DC-0E8122773FAA You could take a look at the data returned by getFileProviderServicesForItem(at:completionHandler:), I tested it with "on iPhone" storage - it returns something for "Application" directory: "com.apple.FileProvider.ValidationV1" -> NSFileProviderService this I could probably not use. At other levels (e.g. ".../Application/UUID" it returns "No valid file provider found from URL" The mentioned API's were previously unknown to me.. In fairness I didn't expect them to be at the FileManager level, more at LaunchServices / NSWorkspace or similar.. I also tried specifying "includingResourceValuesForKeys" keys with the hope that'd help me revealing the bundleID name but wasn't successful with that so far. Thanks anyway!
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
Kevin, thank you for your help and for the specific advices to check on macOS and to check after restart. I created a small test bench app that allows testing most aspects of url bookmarks in an interactive manner. You may find that useful (attached): BookmarksBench.swift It's a single file SwiftUI app that works on iOS and macOS. If it's feasible, I'd recommend testing your code as a "native" macOS app (not the simulator or in compatibility mode). macOS is better at enforcing the "right" behavior, so code that works there will generally work on iOS. Yeah, I noticed a few differences with the above test bench app. iOS seems to ignore withoutImplicitStartAccessing flag, but that's only after app restart (or device restart?). If I resolve the bookmark in the same session where I picked the file/folder it's a slightly different behaviour - when the withoutImplicitStartAccessing is off (that's default) there's one extra "access count" happening, i.e. if I resolve the bookmark N times I have to stop access N+1 times for it to stop working. FTM, I found withoutImplicitStartAccessing flag (specifically being off by default and existing at all) is probably causing more harm than good. Do devs realise they need to call "stop access" after resolving bookmark? Explicit start/stop makes it more obvious what to do, and the ideal API would be something like "withAccess { callback }" that would automatically stop access when callback returns, or this: URL.resolvingBookmarkData(data) { url, error in // url access is only valid here } Make sure you test how things work after you reboot the device. One of the complicating factors here is that the kernel is what's tracking the access here, which can have unexpected side effects. Good to know! However it would be extremely helpful if we did have some (dev only?) means to simulate the effect without actual restart, or even better if it was just working correctly without the need of app or device restart to begin with. BTW, is there no way to get a more meaningful app name on iOS, like the Files app itself is showing other than this bundleID form? /private/var/mobile/Containers/Data/Application/F103656D-99AA-4131-B6FC-CCC9C71606D6/Documents As a user I know the name as I've just seen it (and selected) in Files. Cheers,
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
I figured out some further details: when I get a file or folder URL from the picker I need to call startAccessingSecurityScopedResource on it first prior to converting it to bookmark. If I don't do that and try to convert that URL to bookmark I am seeing this error in the console: [ERROR] getattrlist(<AppContainers>/7{34}3/D{7}s/2{8}2/N{2}1/0{8}7/1{6}3/2{69}0.png) = 1 however the call to make bookmark: url!.bookmarkData(options: [], includingResourceValuesForKeys: nil, relativeTo: nil) doesn't return an error. For a folder URL it's even less visible: no error from the call (same as for file URL) but also nothing in the console as a hint. Later on (perhaps on a different lunch) when I read a bookmark (file or folder) I don't need to call startAccessingSecurityScopedResource on it (not sure if that's intentional behaviour or not).
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to iOS folder bookmarks
But I don't see it working for a folder bookmark even if I quit the app and immediately launch it again, in which case (I assume) volume remounting is not a concern – it's the folder in Files on the iPhone itself, not cloud or anything like that. It works for the file bookmarks though, so the workaround I had in mind was to iterate through the whole hierarchy, create the corresponding mirroring tree of bookmarks, persist that tree and later on use file bookmarks from that tree, but that's quite awkward, besides it takes quite a while to build that tree for a large folder hierarchy.
Topic: App & System Services SubTopic: Core OS Tags:
Aug ’25
Reply to "Local network prohibited" 2025 edition
Thank you. Restarting the device helped indeed. Looks like there's some in memory cache that is not fully updated when I delete / reinstall the app (despite OS is prompting "allow local network" on the first run after reinstall and I answer "yes" to that). I probably have answered "No" the very first time and that somehow polluted that memory cache forever until restart.
Jun ’25