'Safe handling of Apple TabularData table data in Swift
I have successfully imported a simple two-column CSV file using DataFrame. Now I want to turn the two cells in each row into strings. The left or right side will occasionally be missing a value; see print output. table
When I try to process a row with a nil cell, the program crashes with "Fatal error: Unexpectedly found nil while unwrapping an Optional value"
So my question is, how do I turn the cells into strings ("" if Nil) safely?
Complete ContentView code below, thanks in advance for any help.
import SwiftUI
import TabularData
struct ContentView: View {
@State var openFile = false
var body: some View {
VStack {
Button(action: {openFile.toggle()}, label: {
Text("Open")
})
}.fileImporter(
isPresented: $openFile,
allowedContentTypes: [.commaSeparatedText],
allowsMultipleSelection: false) { (result) in
do {
let fileURL = try result.get().first
if fileURL!.startAccessingSecurityScopedResource() {
print(fileURL!)
importTable(url: fileURL!)
}
fileURL!.stopAccessingSecurityScopedResource()
} catch {
print("Unable to read file contents")
print(error.localizedDescription)
}
}
}
func importTable(url: URL) {
var importerTable: DataFrame = [:]
let options = CSVReadingOptions(hasHeaderRow: false, delimiter: ",")
do {
importerTable = try DataFrame(
contentsOfCSVFile: url,
options: options)
} catch {
print("ERROR reading CSV file")
print(error.localizedDescription)
}
print("\(importerTable)")
importerTable.rows.forEach { row in
let leftString = row[0]! as! String
let rightString = row[1]! as! String
print("Left: \(leftString) Right: \(rightString)")
}
}
}
Solution 1:[1]
A fileImporter context is quite insecure, any carelessly written exclamation mark can crash the app.
First you have to check fileURL and abort the import if it's nil
guard let fileURL = try result.get().first else { return }
if fileURL.startAccessingSecurityScopedResource() {
print(fileURL)
importTable(url: fileURL)
}
fileURL.stopAccessingSecurityScopedResource()
In importTable you must not continue after a do - catch if an error is thrown and you have to check if the CSV file contains three items per row.
func importTable(url: URL) {
var importerTable: DataFrame = [:]
let options = CSVReadingOptions(hasHeaderRow: false, delimiter: ",")
do {
importerTable = try DataFrame(
contentsOfCSVFile: url,
options: options)
print("\(importerTable)")
importerTable.rows.forEach { row in
if row.count > 2 {
let leftString = row[1] as! String
let rightString = row[2] as! String
print("Left: \(leftString) Right: \(rightString)")
}
}
} catch {
print("ERROR reading CSV file")
print(error.localizedDescription)
}
}
Sources
This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.
Source: Stack Overflow
| Solution | Source |
|---|---|
| Solution 1 |
