- July 30, 2025
- Mins Read
func foo(a: Int = 1, b: String = "hi") { … }
func connect(to host: String, port: Int = 80, useSSL: Bool = false) { … }
connect(to: "example.com")
// is treated as:
connect(to: "example.com", port: 80, useSSL: false)
Defaults aren’t limited to literals; any expression that’s valid in that scope is allowed:
let globalTimeout = 30
func fetchData(endpoint: String,
timeout: TimeInterval = TimeInterval(globalTimeout),
cache: Bool = true)
{
// …
}
or even calling other functions:
func now() -> Date { Date() }
func log(message: String, at timestamp: Date = now()) {
print("[\(timestamp)]", message)
}
Swift distinguishes between the external label (used by callers) and the internal name (used in the function body):
func move(from start: Point, to end: Point = .zero) { … }
// Callers write:
move(from: p1) // second uses default .zero
move(from: p1, to: p2)
You can even omit the external label (_
) while still providing a default:
func increment(_ value: Int = 1) -> Int {
return base + value
}
increment() // adds 1
increment(5) // adds 5
You can combine variadics and defaults—though variadics always subsume any values provided:
func sum(_ values: Int..., initial: Int = 0) -> Int {
return values.reduce(initial, +)
}
sum() // returns 0
sum(1, 2, 3) // returns 6
sum(4, 5, 6, initial: 10) // returns 25
Swift’s rich error‐handling model gives you fine-grained control over failure paths, cleanup, and propagation.
enum
s conforming to Error
are the standard way:
enum DataError: Error {
case notFound(path: String)
case invalidFormat(reason: String)
case permissionDenied
}
throws
and use throw
anywhere inside:
func loadJSON(from path: String) throws -> [String: Any] {
guard FileManager.default.fileExists(atPath: path) else {
throw DataError.notFound(path: path)
}
// … attempt to read & parse …
guard let data = try? Data(contentsOf: URL(fileURLWithPath: path)) else {
throw DataError.invalidFormat(reason: "Unreadable data")
}
// parse JSON…
return jsonObject
}
rethrows
:func perform<T>(_ work: () throws -> T) rethrows -> T {
// If `work` throws, this function will too.
return try work()
}
try
. Omitting try
is a compile-error.try?
or try!
to convert or force-unwrap if needed, but most of the time you’ll use plain try
to let errors bubble up.do-catch
do {
let json = try loadJSON(from: "config.json")
print("Loaded config:", json)
} catch DataError.notFound(let path) {
print("File not found at \(path)")
} catch DataError.invalidFormat(let reason) {
print("Bad format:", reason)
} catch {
print("Unexpected error:", error)
}
catch
lets you extract associated values.catch
without a pattern catches any error.defer
If you need guaranteed cleanup—regardless of success or failure—use defer
:
func processFile(_ path: String) throws {
let handle = try FileHandle(forReadingFrom: URL(fileURLWithPath: path))
defer {
handle.closeFile()
print("File closed")
}
// If any throw happens below, the defer block still runs
let data = try handle.readToEnd() ?? Data()
// …
}
defer
blocks; they execute in reverse order of appearance.try?
and try!
try?
nil
on error:
let maybeJSON = try? loadJSON(from: "config.json")
// maybeJSON is [String: Any]?; error is swallowed
try!
let guaranteedJSON = try! loadJSON(from: "default.json")
// Only use if you're 100% sure it can't fail
When calling Swift throwing functions from Obj-C (or Cocoa APIs expecting NSError**
):
@objc func objcLoadJSON(from path: String, error: NSErrorPointer) -> [String: Any]? {
do {
return try loadJSON(from: path)
} catch let err as NSError {
error?.pointee = err
return nil
}
}
You can catch an error, wrap or annotate it, then rethrow:
func enhancedLoad(path: String) throws -> [String: Any] {
do {
return try loadJSON(from: path)
} catch {
throw DataError.invalidFormat(reason: "Failed at path \(path): \(error)")
}
}
This lets you add context while preserving the error-handling flow.
PermissionsSwiftUI displays and handles permissions in SwiftUI. It is largely inspired by SPPermissions. The UI is highly customizable and resembles an Apple style. ...
Introduction PagerTabStripView is the first pager view built in pure SwiftUI. It provides a component to create interactive pager views ...
1. Taking Action When a Property Changes: Property Observers Swift lets you observe and respond to changes in a property’s ...