Using SwiftUI's .fileImporter
to get a 'user selected' URL for a directory, when using FileManager
's URL enumerator
, nextObject()
returns nil.
Entitlement:
<key>com.apple.security.files.user-selected.read-only</key>
<true/>
(Tried read-write, same result)
From SwiftUI view
.fileImporter(
isPresented: $showingOpenPanel,
allowedContentTypes: [.fileURL, .directory],
onCompletion: { result in
viewModel.onImport(result: result)
}
)
Getting valid URL (targetURL
), but cannot get any file from enumerator:
// In ViewModel
switch result {
case .success(let url):
targetURL = url // URL is valid ("/Users/<username>/Desktop/MyFolder/")
...
let enumerator = FileManager.default.enumerator(at: targetURL, includingPropertiesForKeys: nil) // enumerator is not nil
enumerator?.nextObject() // nil
Removing Sandbox entitlement resolve the issue (so it's Sandbox related). But is not user-selected
means that user pick from the OpenPanel using fileImporter
?
According to the documentation, fileImporter
gives you security-scoped URLs, so you will need to call startAccessingSecurityScopedResource
and stopAccessingSecurityScopedResource
to access them.
e.g.
if targetURL.startAccessingSecurityScopedResource() {
defer { targetURL.stopAccessingSecurityScopedResource() }
let enumerator = FileManager.default.enumerator(at: targetURL, includingPropertiesForKeys: nil)
// do things with the enumerator...
print(enumerator?.nextObject())
} else {
// fail to access the URL, handle this appropriately
}
You should also create a bookmark for the URL if you need to access it at a later date. See bookmarkData
and init(resolvingBookmarkData:)
.
For more info, see the sections about security scopes in the NSURL
documentation page.