- August 28, 2025
- Mins Read
Defining and Calling Functions
A function bundles work behind a name. Syntax:
func functionName(argumentLabel parameterName: Type) -> ReturnType {
// body
}
Parameters are read-only constants inside the body. Return values are explicit after ->.
Void / (): means “nothing meaningful returned.”func parse(_ text: String) -> Int? { Int(text) }
Use empty parentheses:
func resetGame() {
score = 0
}
resetGame()
Even with no inputs, returning a value is fine:
func currentTimestamp() -> TimeInterval { Date().timeIntervalSince1970 }
Comma-separate them. They’re evaluated left to right, and all must be supplied (unless defaults exist).
func drawLine(from start: CGPoint, to end: CGPoint, width: CGFloat) { /*...*/ }
Parameters are immutable—if you want to modify an argument for the caller, consider inout (see below).
If there’s no ->, the return type is Void (an empty tuple ()).
func log(_ msg: String) { print(msg) } // implicit Void
Use this for side-effect functions. If you later need a result, you can change the signature—call sites may need updates.
Swift favors tuples for lightweight multi-returns:
func stats(of numbers: [Int]) -> (min: Int, max: Int, avg: Double)? {
guard let first = numbers.first else { return nil }
var minV = first, maxV = first, total = 0
for n in numbers { minV = min(minV, n); maxV = max(maxV, n); total += n }
return (minV, maxV, Double(total)/Double(numbers.count))
}
Pros:
Cons:
If the body is a single expression, you can omit return:
func hypotenuse(a: Double, b: Double) -> Double { sqrt(a*a + b*b) }
This also applies to computed properties and closure literals. For more complex bodies, explicit return keeps clarity.
Each parameter can have:
Syntax: func f(external internal: Type)
Defaults:
This is why you often see “swifty” APIs read like sentences.
You craft labels to communicate intent:
func insert(_ item: Item, at index: Int) { /*...*/ }
func request(resource url: URL, timeout seconds: TimeInterval) { /*...*/ }
The second example reads well when called:
request(resource: someURL, timeout: 5)
Use _ for the external label to remove it:
func pow(_ base: Int, _ exp: Int) -> Int { /*...*/ }
pow(2, 8)
Great for math-like, positional parameters where labels add noise. Avoid overusing _: readability matters.
Defaults reduce call-site verbosity:
func toast(_ message: String, duration: TimeInterval = 2.0, position: Position = .bottom) { /*...*/ }
toast("Saved!") // uses both defaults
toast("Saved!", duration: 4.0) // override one
Placement tip: put defaults at the end so callers can omit trailing ones conveniently.
Collect a variable number of args into an array:
func average(_ values: Double...) -> Double {
guard !values.isEmpty else { return .nan }
return values.reduce(0, +) / Double(values.count)
}
average(1, 3, 5, 7)
Rules & gotchas:
[Type].inout or default values on the same parameter is not allowed.inout lets a function modify the caller’s variable (copy-in, copy-out semantics):
func clamp(_ value: inout Int, to range: ClosedRange<Int>) {
value = min(max(value, range.lowerBound), range.upperBound)
}
var speed = 120
clamp(&speed, to: 0...100) // speed becomes 100
&.let struct variable.inout can obscure data flow; prefer returning a new value when possible.Every function has a first-class type:
(Int, Int) -> Int // takes two Ints, returns Int
() -> Void // takes nothing, returns nothing
(String) throws -> Int // can throw
(Double) async -> Int // async function
Note:
throws, async are part of the type—so you must match them when assigning or passing.You can store, pass, and compare functions like any other value:
func add(_ x: Int, _ y: Int) -> Int { x + y }
let op: (Int, Int) -> Int = add
op(2, 3) // 5
Closures ({ ... }) are just inline values of a function type.
Higher-order functions take functions:
func transform(_ value: Int, with f: (Int) -> Int) -> Int {
f(value)
}
let doubled = transform(8) { $0 * 2 }
Benefits:
Return functions to let callers configure behavior:
func makeFilter(min: Int) -> (Int) -> Bool {
{ $0 >= min }
}
let atLeastTen = makeFilter(min: 10)
atLeastTen(12) // true
Closures capture context (min) lexically. This is the foundation of many Swift APIs (e.g., map, filter, sorted(by:)).
Define helpers inside other functions to keep them private and close to use:
func chooseDirection(backward: Bool) -> (Int) -> Int {
func stepForward(_ x: Int) -> Int { x + 1 }
func stepBackward(_ x: Int) -> Int { x - 1 }
return backward ? stepBackward : stepForward
}
@discardableResult: silence “result unused” warnings for functions where ignoring the result is fine.rethrows: a function only throws if the closure parameter throws.
func map<T, U>(_ values: [T], _ transform: (T) throws -> U) rethrows -> [U] { /*...*/ }
async/await: make functions asynchronous. Their type and call sites must use await and possibly try.defer: run code on function exit regardless of return path—great for cleanup.@available, @inline, etc.) add metadata and constraints.func swapValues<T>(_ a: inout T, _ b: inout T) { let t = a; a = b; b = t }
@escaping if stored or executed after the function returns (common in async APIs).func name(label param: Type = default, _ unlabeled: Type..., inoutParam: inout Type) throws -> ReturnType {
// body
return value // or omit if single expression
}
This package provides you with an easy way to show tooltips over any SwiftUI view, since Apple does not provide ...
SimpleToast is a simple, lightweight, flexible and easy to use library to show toasts / popup notifications inside iOS or ...
Create Toast Views with Minimal Effort in SwiftUI Using SSToastMessage. SSToastMessage enables you to effortlessly add toast notifications, alerts, and ...