I am trying to list all PDFs inside a folder that is stored in my Xcode project using SwiftUI, but after trying many different methods I found on here I cannot get it working.
Currently I am using file manager to list the items but when I try and print or list the items found it returns nil
.
I have added the PDFs by dragging them into the Xcode project. I have also made sure that they are in my Copy Bundle Resource so I can use FileManager. See below:
Here is my Xcode structure, I am trying to list all items inside PDF
. As you can see below the PDFs are stored outside the main folder structure in "/Swift/Products/Detail/Tab5/PDF", so when trying to list the files using Bundle.main.bundlePath
, it looks at products.app
.
Here is the code where I am trying to use FileManager to find all PDFs inside the folder:
struct ProductTab5View: View {
@State var files = getFiles()
var body: some View {
VStack{
ForEach(0..<files.count, id: .self) { item in
Text(files[item])
}
}
}
}
func getFiles() -> Array<String>{
// Get document directory url
let documentsUrl = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
var files: [String] = []
do {
// Get the directory contents urls (including subfolders urls)
let directoryContents = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil)
print(directoryContents)
// filter directory contents:
let pdfFiles = directoryContents.filter{ $0.pathExtension == "pdf" }
let pdfFileNames = pdfFiles.map{ $0.deletingPathExtension().lastPathComponent }
files.append(contentsOf: pdfFileNames)
} catch {
print(error)
}
return files
}
2
Answers
There are a few potential problems with your current code.
The first is this line:
Unless you have gone through a process separately from what you’ve shown of adding all of these files to the app’s document directory, then there’s no reason to believe that these files will be there. In other words: your Xcode project is not the same as your app’s document directory. Think of the app’s document directory as a place where you may store user-created or perhaps downloaded content as managed by the app — not Xcode itself.
Next thing to check is whether all of these files are truly added to your target. Check your target’s "Build Phases" -> "Copy Bundle Resources" section to see if they appear there.
If they do, you can use FileManager, but you have to access the correct directory, which is inside the main bundle — not the app’s user document directory.
The following answer goes into details about this (including making sure you create folder references): Getting a list of files in the Resources folder – iOS
The gist will be doing something like this:
and then using FileManager to list the documents in that path.
Note that you can also get all the files (including subdirectories) recursively by doing something like this:
By using the above code during your debugging process, this should give you an insight into what your directory structure is really like inside your bundle. Once you’ve figured that out, adjust the previous code sample to be something like:
which will give you just the files in the one subdirectory you want once you fill in
mySubPath
. Note that if you want recursive search, you can use the code sample above.You may want to exclude non-file items eventually — see this answer for more details about recursive directory lists in Swift: listing all files in a folder recursively with swift
In such a way resources are copied flat into root application bundle, not user ‘s
Documents
as it was tried in provided code snapshot (and noPDF
sub-directory is created for you).So the solution would be just to iterate internal pdf files, like
Tested with Xcode 12.1 / iOS 14.1