Foundation Essentials

This section documents the Swift 6 language mode as shipped by Swift 6.3, as published in The Swift Programming Language at docs.swift.org, which is the reference these pages are written and verified against. 6.4-beta-only features are always flagged as such — never presented as baseline.

This content was generated with the assistance of AI and should be verified against docs.swift.org before being relied on in production.

This section’s bibliography lists the reference material consulted while preparing these pages.

Everything documented so far in this reference belongs to the Swift module, available on every platform with no import beyond the language itself. Foundation is a separate, much larger module that layers dates, networking, the filesystem and other everyday utilities on top — this page covers the pieces most Swift code reaches for.

What Foundation Adds, and swift-foundation

Foundation is not part of the Swift language or its standard library — it is import`ed explicitly, and historically was only fully available on Apple platforms via `Foundation/CoreFoundation. The swift-foundation project reimplements Foundation’s essential types (Date, Calendar, Data, URL, JSONEncoder, …​) in pure Swift, so the same behavior now ships consistently on Linux and other non-Apple platforms too, without the historical gaps between Foundation and its open-source swift-corelibs-foundation counterpart. FoundationEssentials is the lighter-weight module swift-foundation exposes for code that needs these core types without the rest of Foundation’s larger surface (notifications, NSObject-based bridging, and Apple-platform-only APIs).

import Foundation   // the full module: Date, URL, FileManager, URLSession, NotificationCenter, ...
// or, on platforms/targets that only need the essentials:
// import FoundationEssentials

Date, Calendar, DateComponents

let now = Date()                            // an absolute point in time, independent of any calendar or time zone
let later = now.addingTimeInterval(3600)    // one hour later
now.timeIntervalSince(later)                 // -3600

var calendar = Calendar(identifier: .gregorian)
calendar.timeZone = TimeZone(identifier: "Europe/Madrid")!

let components = calendar.dateComponents([.year, .month, .day, .hour], from: now)
components.year                              // e.g. 2026

var startOfNextMonth = DateComponents()
startOfNextMonth.month = 1
let nextMonth = calendar.date(byAdding: startOfNextMonth, to: now)!

Date is deliberately calendar-agnostic — just a number of seconds relative to a reference date. Converting a Date to or from year/month/day/hour concepts always goes through a Calendar (which calendar system, which time zone), since "what day is it" is meaningless without both.

Date.FormatStyle and DateFormatter

let formatted = now.formatted(.dateTime.year().month(.wide).day().hour().minute())   // "September 13, 2026 at 9:41 AM"
let iso = now.formatted(.iso8601)

let legacyFormatter = DateFormatter()
legacyFormatter.dateStyle = .medium
legacyFormatter.timeStyle = .short
let legacyFormatted = legacyFormatter.string(from: now)

Date.FormatStyle (.formatted(…​)) is the modern, Codable-friendly, locale-aware API, built on the same FormatStyle protocol behind Measurement’s and numbers' own `.formatted(). DateFormatter is the older NSFormatter-based API — still common in existing code and still fully supported, but Date.FormatStyle is preferred for new code.

TimeZone, Locale, Measurement

let tokyo = TimeZone(identifier: "Asia/Tokyo")!
let spanish = Locale(identifier: "es_ES")

let distance = Measurement(value: 42.195, unit: UnitLength.kilometers)
distance.converted(to: .miles).value         // ~26.22
distance.formatted()                          // locale-aware: "42,195 km" under a comma-decimal locale

TimeZone and Locale parameterize almost every other Foundation date/number API (Calendar, DateFormatter, NumberFormatter) rather than being consumed directly very often. Measurement<UnitType> pairs a numeric value with a Dimension (UnitLength, UnitDuration, UnitTemperature, …​), converting between units and formatting them without hand-written conversion factors.

URL, Data, FileManager

let fileURL = URL(filePath: "/tmp/notes.txt")               // file-system URL
let remoteURL = URL(string: "https://example.com/api/users")!

let text = "hello, file"
try text.write(to: fileURL, atomically: true, encoding: .utf8)
let readBack = try String(contentsOf: fileURL, encoding: .utf8)

let bytes: Data = try Data(contentsOf: fileURL)
bytes.count

let fm = FileManager.default
fm.fileExists(atPath: fileURL.path)
try fm.createDirectory(at: fileURL.deletingLastPathComponent(), withIntermediateDirectories: true)
try fm.removeItem(at: fileURL)

URL represents both remote and local (file://) locations uniformly; Data is Foundation’s byte-buffer type, bridging to [UInt8] where needed. FileManager is the entry point for everything else file-system-related: existence checks, directory creation/traversal, copying, moving, and deleting.

URLSession with async/await

struct User: Codable {
    var id: Int
    var name: String
}

func fetchUser(id: Int) async throws -> User {
    let url = URL(string: "https://example.com/api/users/\(id)")!
    let (data, response) = try await URLSession.shared.data(from: url)

    guard let httpResponse = response as? HTTPURLResponse, httpResponse.statusCode == 200 else {
        throw URLError(.badServerResponse)
    }
    return try JSONDecoder().decode(User.self, from: data)
}

URLSession.shared.data(from:)/data(for:) are async from the start — no completion-handler bridging needed — and pair naturally with Codable (see Codable and Serialization) for decoding the response body, and with Async/Await and Tasks for the async/await mechanics themselves.

UUID, NotificationCenter, NumberFormatter

let id = UUID()                             // e.g. E621E1F8-C36C-495A-93FC-0C247A3E6E5F
UUID(uuidString: "E621E1F8-C36C-495A-93FC-0C247A3E6E5F")   // parses back, or nil if malformed

NotificationCenter.default.addObserver(forName: .NSSystemClockDidChange, object: nil, queue: .main) { note in
    print("clock changed:", note)
}
NotificationCenter.default.post(name: Notification.Name("MyCustomEvent"), object: nil)

let currency = NumberFormatter()
currency.numberStyle = .currency
currency.locale = Locale(identifier: "en_US")
currency.string(from: 19.99)                  // "$19.99"

UUID wraps a 128-bit universally-unique identifier with Codable/Hashable/CustomStringConvertible conformance built in. NotificationCenter is Foundation’s process-wide publish/subscribe mechanism, predating Combine and AsyncSequence but still widely used, especially for system notifications. NumberFormatter formats numbers as currency, percentages, or spelled-out text, locale-aware exactly like DateFormatter.

Bridging Between Swift and NS Types

let swiftString: String = "hello"
let nsString = swiftString as NSString      // toll-free bridged: no copy on Apple platforms

let swiftArray: [Int] = [1, 2, 3]
let nsArray = swiftArray as NSArray          // bridges element-by-element

let swiftDict: [String: Int] = ["a": 1]
let nsDict = swiftDict as NSDictionary

String/NSString, Array/NSArray, Dictionary/NSDictionary, and several other pairs are toll-free bridged on Apple platforms — convertible with as, often without copying — because the Swift standard library types were designed to interoperate directly with their long-established Foundation counterparts. On Linux, where the NS-prefixed classes are Foundation’s own Swift implementations rather than Objective-C runtime classes, the same as conversions still work, but without the toll-free (zero-copy) guarantee.

See Also