How to Read CSV Files and Display as Objects in Desktop Flutter Applications using Swift

Sezer Ufuk Yavuz
4 min readSep 16, 2023

--

In the evolving landscape of cross-platform development, Flutter has made a name for itself, not just in mobile, but also in desktop applications. While Dart is Flutter’s primary language, there are cases when we need to leverage native code, particularly for macOS development where Swift shines. In this guide, we’ll take a deep dive into the process of reading CSV files in Swift and integrating them seamlessly into a Flutter desktop application.

1. Preparation: Understanding Your CSV

First and foremost, it’s paramount that the CSV file is structured consistently. Each row should represent an object, and the first row typically contains headers, representing the property names of objects.

2. Visualizing the Data Structure

Before converting your CSV into Swift-readable objects, visualize a sample object in JSON format. This step aids in generating Swift models in subsequent steps. For instance, your data might look something like:

{
"index":1,
"organizationID":"FAB0d41d5b5d22c",
"name":"Ferrell LLC",
"website":"https://price.net/",
"country":"Papua New Guinea",
"description":"Horizontal empowering knowledgebase",
"founded":1990,
"industry":"Plastics",
"numberOfEmployees":3498
}

3. Swift Model Generation with quicktype.io

  • Navigate to quicktype.io.
  • Paste your sample JSON.
  • Select Swift as the target language.
  • This platform quickly generates a Swift model, making data parsing effortless.

4. Flutter Project Configuration in Xcode:

Open the macOS folder of your Flutter project, which should launch Xcode, as demonstrated in the provided image.

5. Structuring Swift Models:

  • Under the Runner directory, create a Models folder.
  • Inside Models, create a new Swift file called OrganizationModel.swift.
  • Copy the model structure from quicktype.io into this file.
  • Add an extension to this model to facilitate easier data referencing.

Model with extension

Extension code example

struct OrganizationModel: Codable {
let index: Int
let organizationID, name: String
let website: String
let country, description: String
let founded: Int
let industry: String
let numberOfEmployees: Int
}


extension OrganizationModel {
init?(from row: DataFrame.Row) {
guard let index = row["Index"] as? Int,
let organizationID = row["Organization Id"] as? String,
let name = row["Name"] as? String,
let website = row["Website"] as? String,
let country = row["Country"] as? String,
let description = row["Description"] as? String,
let founded = row["Founded"] as? Int,
let industry = row["Industry"] as? String,
let numberOfEmployees = row["Number of employees"] as? Int else {
return nil
}

self.index = index
self.organizationID = organizationID
self.name = name
self.website = website
self.country = country
self.description = description
self.founded = founded
self.industry = industry
self.numberOfEmployees = numberOfEmployees
}
}

6. Integrating the CSV File:

  • Create a directory named Assets inside the Runner directory.
  • Place your CSV file in this directory, ensuring it’s easily accessible.

7. Data Extraction Logic:

  • Inside Runner, initiate a new folder titled Data.
  • Within, create a Swift file named OrganizationsGet.swift. This file houses the logic for fetching and processing CSV data.
  • Here, you’ll use the TabularData package. But, if your macOS version target is below 12, you'll receive a warning.
import Foundation
import TabularData



let url = Bundle.main.url(forResource: "organizations", withExtension: "csv")!
var result = try? DataFrame(contentsOfCSVFile: url)

8. Resolving Potential Version Warnings:

If confronted with a version warning:

  • Go to Runner => Targets => Runner (Flutter symbol) => minimum deployments.
  • Adjust the version to 12.0.

9. Crafting Data Transfer Functions:

Within OrganizationsGet.swift, write a getDataFromCsv function. This function's duty is to parse the CSV data and populate the Swift model.


func getDataFromCsv() -> [OrganizationModel]? {

guard let df = result else {
return nil
}

var organizationModels = [OrganizationModel]()

for row in df.rows {
if let model = OrganizationModel(from: row) {
organizationModels.append(model)
}
}

return organizationModels
}

10. Testing Our Setup:

  • Draft a test function named printOrganizationNames.
  • Call this function within the AppDelegate and run your project.
  • If all is well, the console will print the organization names, signifying that our integration is successful.
func printOrganizationNames(from models: [OrganizationModel]) {
for model in models {
print(model.name)
}
}
if let organizationModels = getDataFromCsv() {
printOrganizationNames(from: organizationModels)
}

Sample csv file: Zip version

My github profile: https://github.com/suysoftware

--

--

Sezer Ufuk Yavuz
Sezer Ufuk Yavuz

Written by Sezer Ufuk Yavuz

Flutter & Swift dev | Specializing in LLM applications for daily ease on macOS  | Founder of ThinkBuddy, enhancing the macOS experience: http://thinkbuddy.io

Responses (1)