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. Also in library
JWT Tokens in PHP: firebase/php-jwt Library and Complete Guide
Task Queues in Go: Overview of async, gocelery, and machinery Libraries
JSON Processing in Rust: serde_json and json Libraries
Sending SMS in Java: Overview and Examples of Using API Libraries (Twilio, Nexmo)
Cryptography in Swift: Encryption and Hashing for iOS/macOS
Recommendations