Working with CSV in Swift (iOS/macOS) — Libraries and Code Examples

Online Python Trainer for Beginners

Learn Python easily without overwhelming theory. Solve practical tasks with automatic checking, get hints in Russian, and write code directly in your browser — no installation required.

Start Course

Working with CSV in Swift (iOS/macOS): Libraries, Parsing, and Examples



CSV (Comma-Separated Values) is one of the most common formats for exchanging tabular data. In the Apple ecosystem (iOS, macOS, watchOS), working with CSV is often required for data import/export, loading configurations, or processing logs. In this article, we will look at the main approaches to working with CSV in Swift: manual parsing, popular libraries (SwiftCSV and CodableCSV), and code examples with explanations.



1. Why Use Libraries for CSV?



The standard Foundation library does not provide ready-made tools for working with CSV. Manual parsing (splitting by commas, handling quotes, escaping characters) quickly becomes cumbersome and error-prone. Libraries solve the following tasks:

  • Correct handling of quotes and escaped characters.
  • Support for different delimiters (comma, tab, semicolon).
  • Streaming reading of large files (without loading entirely into memory).
  • Integration with Codable for automatic deserialization.


2. SwiftCSV Library



SwiftCSV is a lightweight library for reading and writing CSV. It supports rows, dictionaries, and nested arrays. Installation via Swift Package Manager:

// Package.swiftdependencies: [    .package(url: "https://github.com/swiftcsv/SwiftCSV.git", from: "0.9.0")]


Example of reading CSV from a file:

import SwiftCSV

guard let path = Bundle.main.path(forResource: "data", ofType: "csv") else { fatalError("CSV file not found")}let csv = try CSV(url: URL(fileURLWithPath: path))

// Access rows by headersfor row in csv.rows { let name = row["name"] ?? "" let age = row["age"] ?? "" print("\\(name) is \\(age) years old")}

// Access columnslet allNames = csv.columns["name"] ?? []print(allNames)


Writing CSV: The library does not provide a built-in write method, but you can manually construct a string:

func writeCSV(rows: [[String: String]], headers: [String]) -> String {    var csvString = headers.joined(separator: ",") + ""    for row in rows {        let values = headers.map { row[$0] ?? "" }        csvString += values.joined(separator: ",") + ""    }    return csvString}

let csvData = writeCSV(rows: data, headers: ["name", "age"])try csvData.write(to: url, atomically: true, encoding: .utf8)


3. CodableCSV Library



CodableCSV is a powerful library supporting Codable, custom delimiters, streaming reading, and configurable encoding. It is ideal for complex projects.



Installation:

// Package.swiftdependencies: [    .package(url: "https://github.com/dehesa/CodableCSV.git", from: "0.9.0")]


Example of reading with automatic deserialization into a model:

import CodableCSV

struct Person: Codable { let name: String let age: Int let email: String?}

let data = try Data(contentsOf: url)let decoder = CSVDecoder { config in config.headerStrategy = .firstLine // first line is headers config.delimiter = .comma}let people = try decoder.decode([Person].self, from: data)

for person in people { print(person.name, person.age)}


Writing CSV with CodableCSV:

let encoder = CSVEncoder { config in    config.headerStrategy = .firstLine    config.delimiter = .comma}let data = try encoder.encode(people, into: Data.self)try data.write(to: url, options: .atomic)


4. Manual Parsing (Without Libraries)



If the project is small and you want to avoid dependencies, you can implement a simple parser.

Recommendations