首页 > 解决方案 > FileManager 在 Xcode 项目中找不到 PDF 目录

问题描述

我正在尝试使用 SwiftUI 列出存储在我的 Xcode 项目中的文件夹中的所有 PDF,但是在尝试了我在这里找到的许多不同方法之后,我无法让它工作。

目前我正在使用文件管理器列出项目,但是当我尝试打印或列出找到的项目时,它会返回nil

我通过将 PDF 拖到 Xcode 项目中来添加它们。我还确保它们位于我的Copy Bundle Resource中,因此我可以使用 FileManager。见下文:

在此处输入图像描述

这是我的 Xcode 结构,我试图列出里面的所有项目PDF。正如您在下面看到的,PDF 存储在"/Swift/Products/Detail/Tab5/PDF"中的主文件夹结构之外,因此当尝试使用 列出文件时 Bundle.main.bundlePath,它会查看products.app.

在此处输入图像描述

这是我尝试使用 FileManager 查找文件夹内所有 PDF 的代码:

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
}

标签: iosswiftxcodeswiftui

解决方案


您当前的代码存在一些潜在问题。

首先是这一行:

FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first

除非您已经完成了与您所展示的将所有这些文件添加到应用程序的文档目录不同的过程,否则没有理由相信这些文件会在那里。换句话说:您的 Xcode 项目您的应用程序的文档目录不同。将应用程序的文档目录视为您可以存储由应用程序管理的用户创建或下载的内容的地方,而不是 Xcode 本身。

接下来要检查的是是否所有这些文件都真正添加到您的目标中。检查目标的“构建阶段”->“复制捆绑资源”部分,看看它们是否出现在那里。

如果他们这样做,您可以使用 FileManager,但您必须访问正确的目录,该目录位于主包内 - 而不是应用程序的用户文档目录。

以下答案对此进行了详细说明(包括确保创建文件夹引用):Getting a list of files in the Resources folder - iOS

要点将做这样的事情:

if let files = try? FileManager.default.contentsOfDirectory(atPath: Bundle.main.bundlePath) { //may need to dig into subdirectories
   for file in files {
            //manipulate the file
        }
    }

然后使用 FileManager 列出该路径中的文档。

请注意,您还可以通过执行以下操作以递归方式获取所有文件(包括子目录):

let url = URL(fileURLWithPath: Bundle.main.bundlePath)
if let enumerator = FileManager.default.enumerator(at: url, includingPropertiesForKeys: [.isRegularFileKey], options: [.skipsHiddenFiles, .skipsPackageDescendants]) {
    for case let fileURL as URL in enumerator {
        print(fileURL)
    }
}

通过在调试过程中使用上面的代码,这应该可以让您深入了解您的目录结构在您的包中的真实情况。一旦你弄清楚了,将前面的代码示例调整为:

if let files = try? FileManager.default.contentsOfDirectory(atPath: Bundle.main.bundlePath + mySubPath) {
   for file in files {
            //manipulate the file
        }
    }

填写后,它将只为您提供所需的一个子目录中的文件mySubPath。请注意,如果您想要递归搜索,您可以使用上面的代码示例。

您最终可能希望排除非文件项目——有关 Swift 中递归目录列表的更多详细信息,请参见此答案:listing all files in a folder recursive with swift


推荐阅读