Hi,
Is this maybe the wrong way to construct the path url?
Yes, that's the issue here.
Because of how URL mixes both file paths and network paths, some methods do COMPLETELY the wrong thing when called on the wrong URL type. Looking at your code in particular:
if let percentDecoded = "\(dbPath)\(relativeFilePathFromDb)".removingPercentEncoding,
I don't know what your source data was here, but it would be unusual to percent encode (or any broad, text based modification) a file path.
let normalizedUrl = URL(string: url.path, relativeTo: URL(fileURLWithPath: "/"))?.standardizedFileURL {
URL(string:) or it's variant should NEVER be used with file paths. Per the documentation, it parses the input paths based on RFC 3986/1808/1738, which makes the final output... difficult to predict. It often leaves basic ASCII paths unmodified but will completely mangle more complicated unicode characters (for example, emoji), opening the door to all sorts of unexpected failures.
When working with file paths, you should:
-Create paths using fileURL(withPath:) or any of the other initializers that specifically reference "fileURL". However, note that direct URL creation is relatively unusual in a sandboxed app. It's more typical to start with a URL the system "gives" you then modify it using:
-Use appendPathComponent(_:) or one of it's variants to add directory or file names.
-Use deleteLastPathComponent() or one of it's variants to remove directories or file from the path.
Also, as general guidance, I strongly recommend against converting URLs into strings or creating URLs from strings. You should think of a file URL as an opaque reference object that you can modify, NOT simply a "wrapper" around the "true" string path. Three major reasons for this:
-
The URL object itself is what holds the security scope data, so converting back and for between URL and String can leave you with a URL that startAccessingSecurityScopedResource fails on, even though the user gave you access to that path.
-
Using simple string paths to reference files was somewhat reasonable in a world of pure ASCII. It's broken down very badly in a world where all major file system have ended up using a different unicode variant for name storage.
-
Most URLs the system will give you are actually file reference URLs, not "path" references. The documentation has a detailed description of the difference, but the quick summary is that a file reference URL references a specific object in the file system, NOT a specific location. That means it can (generally) provide a valid reference to the same object across moves or renames within the file system, something a path URL can obviously not do.
-Kevin Elliott
DTS Engineer, CoreOS/Hardware