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
-
Codable and Serialization — decoding
URLSessionresponse bodies, andDate/Datacoding strategies. -
Async/Await and Tasks — the
async/awaitmechanics behind `URLSession’s API. -
Error Handling —
throwsandURLErrorfrom networking and file I/O. -
Standard Library Overview — the
Swiftmodule’s own types, which Foundation builds on rather than replaces.