How to access a Security Scoped Resource from a String Path in Swift?
UIDocumentPickerViewController
provides a security-scoped URL to access a resource and it is not possible to make the same from a string path:
If you need a security-scoped URL’s path as a string value (as provided by the path method), such as to provide to an API that requires a string value, obtain the path from the URL as needed. Note, however, that a string-based path obtained from a security-scoped URL does not have security scope and you cannot use that string to obtain access to a security-scoped resource. https://developer.apple.com/documentation/foundation/nsurl
If you need to save or share a location of secured resource in your code you should use bookmarks:
// Get bookmark data from the provided URL
let bookmarkData = try? pickedURL.bookmarkData()
if let data = bookmarkData {
// Save data
...
}
...
// Access to an external document by the bookmark data
if let data = bookmarkData {
var stale = false
if let url = try? URL(resolvingBookmarkData: data, bookmarkDataIsStale: &stale),
stale == false,
url.startAccessingSecurityScopedResource()
{
var error: NSError?
NSFileCoordinator().coordinate(readingItemAt: url, error: &error) { readURL in
if let data = try? Data(contentsOf: readURL) {
...
}
}
url.stopAccessingSecurityScopedResource()
}
}
Frank
Updated on December 29, 2022Comments
-
Frank over 1 year
I'm currently using flutter to pass a
String
of a valid file path to Swift in order to gain access to a security scoped resource (this part might not be relevant)So I have a function that accepts a
String
and goes like this:public func requestAccessToFile(filePath: String) -> Bool { let fileUrl = URL(fileURLWithPath: filePath) return fileUrl.startAccessingSecurityScopedResource() }
I know that
startAccessingSecurityScopedResource
not always returnstrue
but in this case, it should, since if I try to access the file without this returningtrue
I get permissions error.A bit more context: If I try to call that
startAccessingSecurityScopedResource
as soon as I get the URL from the file picker, it does succeed, but if I do it with the function it fails (notice that the function is called with aString
and I'm passing a path without thefile://
protocol. eg. "/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/Documents/afile.pdf"So my guess is that the URL created by the file picker is somehow different that the one I'm creating with the string path. But not sure.
Thanks for your help in advance.
-
Frank almost 3 yearsAhh, an extra comment, it does work on the emulator, it only fails on a physical device.
-
-
Frank almost 3 yearsThanks! Will check the bookmark part today.