Swift Cheatsheet

Input, Output & Parsing

Use this Swift reference while you build software engineering projects, review code for technical interview prep, or polish examples for a software engineer resume.

Reading stdin

while let line = readLine() {        // nil at EOF, newline stripped
    print(line)
}

let header = readLine()!             // one trusted line
let n = Int(readLine()!)!            // one integer on its own line

Parsing numbers and lines

let nums = readLine()!
    .split(separator: " ")
    .map { Int($0)! }                // [Int] from "3 1 4"

let pair = readLine()!.split(separator: " ").map { Int($0)! }
let (a, b) = (pair[0], pair[1])

let doubles = readLine()!.split(separator: ",").compactMap { Double($0) }

split(separator:) returns [Substring] and drops empty fields by default (omittingEmptySubsequences: false keeps them). Int.init and Double.init accept Substring directly.

Fast scanner for large input

Byte-level scanning avoids per-line allocation on big inputs:

import Foundation

final class FastScanner {
    private let data: [UInt8]
    private var idx = 0

    init() {
        data = Array(FileHandle.standardInput.readDataToEndOfFile())
    }

    func readInt() -> Int {
        while idx < data.count, data[idx] == 32 || data[idx] == 10 || data[idx] == 13 {
            idx += 1                                     // skip whitespace
        }
        var sign = 1
        if idx < data.count, data[idx] == 45 {           // '-'
            sign = -1
            idx += 1
        }
        var num = 0
        while idx < data.count, data[idx] >= 48, data[idx] <= 57 {   // '0'...'9' only
            num = num * 10 + Int(data[idx] - 48)
            idx += 1
        }
        return num * sign
    }
}

let sc = FastScanner()
let count = sc.readInt()
let values = (0..<count).map { _ in sc.readInt() }

Both loop conditions are bounds-checked and the digit loop stops at the first non-digit byte.

Output

print("a", "b", 3)                        // "a b 3", space separator
print("a", "b", separator: ", ")          // "a, b"
print("no newline", terminator: "")
print(nums.map(String.init).joined(separator: " "))

// Batch output: one print beats thousands
var out = ""
out.reserveCapacity(1 << 16)
for x in answers { out += "\(x)\n" }
print(out, terminator: "")

JSON with Codable

import Foundation

struct User: Codable {
    let id: Int
    let name: String
    let email: String?               // optional fields tolerate null / missing keys
}

let json = #"{"id": 1, "name": "Ada", "email": null}"#
let user = try JSONDecoder().decode(User.self, from: Data(json.utf8))

let users = try JSONDecoder().decode([User].self, from: arrayData)   // top-level arrays

let encoded = try JSONEncoder().encode(user)
print(String(data: encoded, encoding: .utf8)!)

Codable (= Decodable & Encodable) is synthesized when every stored property conforms. Nested structs decode nested objects automatically.

CodingKeys and strategies

struct Post: Codable {
    let id: Int
    let authorName: String
    let createdAt: Date

    enum CodingKeys: String, CodingKey {   // per-type key mapping
        case id
        case authorName = "author_name"
        case createdAt = "created_at"
    }
}

// Or map every key at once
let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
decoder.dateDecodingStrategy = .iso8601

let encoder = JSONEncoder()
encoder.outputFormatting = [.prettyPrinted, .sortedKeys]
encoder.keyEncodingStrategy = .convertToSnakeCase

For fully dynamic JSON, decode into [String: Any] via JSONSerialization.jsonObject(with:), but prefer typed Codable models whenever the shape is known.