SwiftUI读取CSV文件报错文件未找到,如何读取并展示数据?
SwiftUI 读取CSV文件失败的解决方法
问题描述
尝试在SwiftUI中读取capitals.csv文件,但运行后仅显示Error file cant be found。当前实现的CSV读取函数及视图代码如下:
读取函数代码
import SwiftUI extension String{ //Get the filename from a String func fileName ( ) -> String{ return URL (fileURLWithPath: self).deletingPathExtension().lastPathComponent } //Get the file extension from a String func fileExtension() -> String{ return URL (fileURLWithPath: self).pathExtension } } func readCSV (inputFile: String, separator: String) -> [String]{ //Split the file name let fileExtension = inputFile.fileExtension() let fileName = inputFile.fileName() //Get the file URL let fileURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) let inputFileURL = fileURL[0].appendingPathComponent(fileName).appendingPathExtension(fileExtension) //Get Data do{ let savedData = try String(contentsOf: inputFileURL) return savedData.components(separatedBy: separator) } catch{ return ["Error file cant be found"] } }
视图代码
struct Test: View{ var data = readCSV(inputFile: "capitals.csv", separator: ",") var body: some View{ VStack{ Text(data[0]) } }
问题原因
代码错误地将文件路径指向了用户的文档目录(documentDirectory),但capitals.csv作为项目资源文件,实际存储在App的主Bundle中,因此找不到文件。此外,当前的CSV解析逻辑仅简单按分隔符拆分,未处理换行,无法正确解析CSV的行结构。
解决方案
1. 修正文件路径与解析逻辑
将文件路径改为从Bundle中获取,并优化CSV解析格式:
func readCSV(inputFile: String, separator: String) -> [[String]] { // 从App主Bundle中获取文件URL guard let fileURL = Bundle.main.url(forResource: inputFile.fileName(), withExtension: inputFile.fileExtension()) else { return [["Error file cant be found"]] } do { let savedData = try String(contentsOf: fileURL) // 先按行拆分,再按分隔符拆分每行内容,过滤空行 let rows = savedData.components(separatedBy: .newlines) return rows.compactMap { row in let columns = row.components(separatedBy: separator) return columns.isEmpty ? nil : columns } } catch { return [["Error reading file: \(error.localizedDescription)"]] } }
- 返回类型改为
[[String]],对应CSV的行、列二维结构,更贴合实际数据格式。 - 使用
Bundle.main.url(forResource:withExtension:)获取资源文件的正确路径。
2. 确保CSV文件已添加到项目Target
选中capitals.csv文件,查看右侧File Inspector,确认Target Membership勾选了当前App的target,确保文件被打包到App Bundle中。
3. 优化视图数据加载逻辑
利用SwiftUI的生命周期方法异步加载数据,避免视图初始化时的同步加载问题:
struct Test: View{ @State private var csvData: [[String]] = [] var body: some View{ VStack{ if csvData.isEmpty { Text("Loading data...") } else { // 示例:遍历展示第一行数据,可根据需求调整为多行展示 ForEach(csvData[0], id: \.self) { item in Text(item) .padding(.vertical, 4) } } } .onAppear { csvData = readCSV(inputFile: "capitals.csv", separator: ",") } } }
- 使用
@State存储CSV数据,在视图出现时(onAppear)调用读取函数。 - 增加加载状态提示,提升用户体验。
额外提示
如果CSV包含带引号的字段(如"New York, NY"),简单的components(separatedBy: ",")会拆分错误,此时建议使用成熟的CSV解析库处理复杂格式。
内容的提问来源于stack exchange,提问作者Steven Park
相关产品推荐
相关产品推荐

