Here's a working example for Mac OS (but should be the same for iOS except for the URL setup for the incoming csv file).
The csv test data are in 3 columns, with headers of "Name", "Position" and "Score" - so as to test data types of String, Integer and Double.
The Data Model (ViewModel)
import Foundation
import TabularData
class DataModel {
static let shared = DataModel()
@Published var dataTable: DataFrame?
init() {
getData()
}
func getData() {
var url: URL?
do {
url = try FileManager.default.url(for: FileManager.SearchPathDirectory.downloadsDirectory, in: FileManager.SearchPathDomainMask.userDomainMask, appropriateFor: nil, create: true)
} catch{
print("Failed to get Downsloads URL \(error)")
return
}
let csvOptions = CSVReadingOptions(hasHeaderRow: true, ignoresEmptyLines: true, delimiter: ",")
let fileURL = url?.appendingPathComponent("TestCSV.csv")
do {
dataTable = try DataFrame(contentsOfCSVFile: fileURL!,columns: nil, rows: nil, types: ["Name":CSVType.string,"Position":CSVType.integer,"Score":CSVType.double], options: csvOptions)
} catch {
print("Failed to get load datatable from CSV \(error)")
return
}
}
}
extension DataFrame.Rows : RandomAccessCollection {
}
SwiftUI ContentView
import SwiftUI
import TabularData
struct ContentView: View {
var model = DataModel.shared
var body: some View {
List(model.dataTable!.rows,id:\.index) { row in
HStack{
Text(row["Name"] as! String)
Text(String(row["Position"] as! Int))
Text(String(row["Score"] as! Double))
}
}
}
}
With forced unwrap (as!) the app will crash if the processed column does not contain the correct type, so I tend to use a function that checks and returns a string - which then gets used in the View:
// in Data Model
func columnToString(_ column: Any) -> String {
if let str = column as? String {
return str
}
if let int = column as? Int {
return String(int)
}
if let double = column as? Double {
return String(double)
}
return ""
}
// a row in ContentView
Text(model.columnToString(row["Position"] as Any))
I hope this helps. Regards, Michaela