URL init from bookmark throws with file doesn't exist.

I just created a url bookmark (to be saved to db) and immediately read the bookmark afterwards. This line throws an error Error Domain=NSCocoaErrorDomain Code=4 "The file doesn’t exist."

Code Block swift
let url = try URL(
    resolvingBookmarkData: bookmark,
    options: .withoutUI,
    bookmarkDataIsStale: &isStale
)


This works perfectly fine in iOS 13, but the error throws in 14b3, did something change, or is this a beta bug?
Answered by Bastian Inuk in 629873022
I fixed the issue.

I called defer { url.stopAccessingSecurityScopedResource() } before I actually made the bookmark, maybe a bug in iOS 13 let this through?

Thanks for your help!
Can you show us a little more of your code? I tried reproducing the problem here in my office, using the code below, and it worked as expected (Xcode 12.0b3 on the iOS 14.0b3 simulator).

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"

Code Block
func test() throws {
let docDir = try FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
let file = docDir.appendingPathComponent("test.txt")
try "Hello Cruel World!".write(to: file, atomically: true, encoding: .utf8)
let bookmark = try file.bookmarkData()
var isStale = false
let resolvedFile = try URL(
resolvingBookmarkData: bookmark,
options: .withoutUI,
bookmarkDataIsStale: &isStale
)
print(resolvedFile == file) // prints "true"
}

I got my entire codebase on GitHub, I get the files from the users @Environment(\.importFiles).
Code Block swift
file(multipleOfType: [.audio]) { result in
switch result {
case .success(let urls):
openSong (urls: urls)
break
case .failure(let error):
print(error)
break
case .none:
print("No item was selected")
}
}

GitHub

Because of the weird issue I got from the bookmark thing, I've refactored it so I don't get the URL from the bookmark immediately after. But there's still issues reading the file it seems, which I'm debugging further. (This doesn't return Future<Song, SongError>{ $0(.failure(.coundtReadFile)) } weirdly enough

Code Block swift
func load(url: URL, bookmark: Data) throws -> Future<Song, SongError> {
var loaded: (URL?, Error?) = (nil, nil)
let coordinator = NSFileCoordinator()
url.coordinatedRead(coordinator) { inputURL,inputError in
loaded = (inputURL, inputError)
}
guard let loadURL = loaded.0 else { return Future<Song, SongError>{ $0(.failure(.coundtReadFile)) } }
return Future<Song, SongError> { promise in
self.threadPool.start()
let loaded = self.asyncLoad(url: loadURL, bookmark: bookmark)
loaded.whenSuccess { song in
promise(.success(song))
}
loaded.whenFailure { error in
print(error)
promise(.failure(.coundtReadFile))
}
}
}

GitHub

This function could also be important if you're curious how I get the bookmark.
Code Block swift
func add(url: URL) {
    container.performBackgroundTask { [self] context in
        do {
            let newSong = Songs(context: context)
            let bookmark = try url.bookmarkData()
            newSong.bookmark = bookmark
            fetchSong(url: url, bookmark: bookmark)
        } catch {
            print("An error occured: \(error)")
        }
        try? context.save()
        }
}

GitHub

I see you use the document in the apps sandboxing, which I don't do, so I assume that I did something wrong in requesting access for files outside my apps sandboxing?

Cheers, Bastian Inuk Christensen
Accepted Answer
I fixed the issue.

I called defer { url.stopAccessingSecurityScopedResource() } before I actually made the bookmark, maybe a bug in iOS 13 let this through?

Thanks for your help!
URL init from bookmark throws with file doesn't exist.
 
 
Q