Hello,
I am trying to use the SwiftUI fileImporter to get the URL of a direcotry and access it for the files in it.
If I follow the document( Access the directory’s content ) and use url.startAccessingSecurityScopedResource for each file, it always returns false. but this seems to be different from the documentation. If the current behavior is correct, will the documentation be updated in the future?
Related: Access all files in UIDocumentPick… | Apple Developer Forums
I asked this question because I am concerned that if I remove the standardAccessingSecurityScopedResource to match the current situation, the standardAccessingSecurityScopedResource may become necessary due to future iOS updates.
Also, is there any way to know if the status of the AccessingSecurityScopedResource? It would be helpful if we could callstartAcesingSecurityScopedResource only when needed.
Thanks
Here is a sample code
@main
struct SampleApp: App {
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
struct ContentView: View {
@State private var isShowingImportFolder = false
@State private var isShowingImportFile = false
var body: some View {
VStack(spacing: 48) {
Button("Read Folder") {
isShowingImportFolder = true
}
.fileImporter(isPresented: $isShowingImportFolder, allowedContentTypes: [.folder]) { result in
switch result {
case .success(let url):
processDirectory(url)
case .failure(let error):
print("failed. error: \(error)")
}
}
Button("Read File") {
isShowingImportFile = true
}
.fileImporter(isPresented: $isShowingImportFile, allowedContentTypes: [.data]) { result in
switch result {
case .success(let url):
readFile(url)
case .failure(let error):
print("failed. error: \(error)")
}
}
}
}
private func processDirectory(_ directory: URL) {
guard directory.startAccessingSecurityScopedResource() else {
fatalError("failed. directory.startAccessingSecurityScopedResource")
}
defer { directory.stopAccessingSecurityScopedResource() }
var error: NSError?
NSFileCoordinator().coordinate(readingItemAt: directory, error: &error) { url in
let urls = try! FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: [.nameKey, .isDirectoryKey])
urls.lazy
.filter { !$0.hasDirectoryPath }
.forEach { readFile($0) }
}
}
private func readFile(_ url: URL) {
guard url.startAccessingSecurityScopedResource() else {
print("failed access. \(url.path)")
return
}
defer { url.stopAccessingSecurityScopedResource() }
let data = try! Data(contentsOf: url)
print("file.path: \(url.path()), size: \(data.count)")
// read file...
}
}