Swift Argument Labels and Default Values Explained

Swift functions are designed to read clearly at the call site, and two features that make that possible are argument labels and default values. In this article, you will learn what argument labels are, how they differ from parameter names, how default values reduce repetitive code, and how to avoid common errors when calling or declaring functions.

Quick answer: In Swift, an argument label is the name you use when calling a function, while the parameter name is the name used inside the function body. A default value lets a parameter be omitted during a call because Swift automatically supplies a predefined value.

Difficulty: Beginner

Helpful to know first: basic Swift syntax, how to declare and call simple functions, and common value types like String, Int, and Bool.

1. What Is Argument Labels & Default Values?

Argument labels and default values are part of Swift function parameter design. They help make function calls more readable and more flexible.

For example, a function call like sendMessage(to: "Ava") is easier to understand than a call with unlabeled values. Swift treats that clarity as an important part of API design.

These features are also commonly confused with each other. An argument label is not the same thing as the local parameter name, and a default value does not make a parameter optional in the type-system sense. You will see those differences throughout the article.

2. Why Argument Labels & Default Values Matters

Good function design matters because functions are used everywhere in Swift. If a function call is hard to read, every place that uses it becomes harder to understand.

Argument labels matter because they:

Default values matter because they:

You should use argument labels when they improve readability. You should use default values when one value is the normal choice in most calls. You should avoid default values when they hide behavior that needs to be explicit or when several defaults make a function call ambiguous to the reader.

3. Basic Syntax or Core Idea

Declaring a function with an argument label

In Swift, each parameter can have an external name for callers and a local name for use inside the function body.

func greet(person name: String) -> String {
    return "Hello, \(name)!"
}

Here, person is the argument label used by the caller, and name is the parameter name used inside the function.

let message = greet(person: "Mia")
print(message)

The call site reads clearly because the label describes the role of the value.

Omitting an argument label with an underscore

If you do not want a label at the call site, use an underscore.

func square(_ number: Int) -> Int {
    return number * number
}
let result = square(4)
print(result)

This is useful when the meaning is already obvious from the function name.

Adding a default value

A parameter can provide a value that Swift will use automatically if the caller leaves that argument out.

func greet(person name: String, politely: Bool = true) -> String {
    if politely {
        return "Hello, \(name)."
    } else {
        return "Hey, \(name)!"
    }
}

You can call this function with or without the second argument.

print(greet(person: "Mia"))
print(greet(person: "Mia", politely: false))

The first call uses the default value. The second call overrides it.

4. Step-by-Step Examples

Example 1: A single labeled parameter

This example shows the simplest case where the label helps the call read clearly.

func openAccount(for customerName: String) {
    print("Opening account for \(customerName)")
}

openAccount(for: "Jordan")

The label for makes the call more expressive than a plain unlabeled string.

Example 2: Different external and internal names

Sometimes the best call-site label is not the best local variable name. Swift lets you choose both.

func calculateArea(width w: Double, height h: Double) -> Double {
    return w * h
}

let area = calculateArea(width: 5.0, height: 3.0)
print(area)

Callers see descriptive labels, while the function body uses short local names.

Example 3: Omitting a label where the function name is enough

For some mathematical or obvious operations, a label would add noise instead of clarity.

func repeatText(_ text: String, count: Int) -> String {
    return String(repeating: text, count: count)
}

let banner = repeatText("*", count: 10)
print(banner)

The first argument is obvious from the function name, but the second argument benefits from a label because count: explains the meaning of the integer.

Example 4: A default value for common behavior

This example shows how default values make the common case shorter.

func createUser(name: String, isAdmin: Bool = false) {
    print("User: \(name), admin: \(isAdmin)")
}

createUser(name: "Lena")
createUser(name: "Sam", isAdmin: true)

Most users are probably not administrators, so false is a sensible default.

Example 5: Multiple defaults in one function

Default values can be used for more than one parameter, but they should still keep the call understandable.

func connect(to host: String, port: Int = 443, useHTTPS: Bool = true) {
    print("Connecting to \(host) on port \(port), HTTPS: \(useHTTPS)")
}

connect(to: "example.com")
connect(to: "localhost", port: 8080, useHTTPS: false)

This approach works well when the defaults are obvious and commonly needed.

5. Practical Use Cases

6. Common Mistakes

Mistake 1: Calling a function without the required argument label

In Swift, labels are part of the function signature at the call site. If a parameter has an argument label, you must use it when calling the function.

Problem: This call leaves out a required label, so Swift reports an error such as Missing argument label 'person:' in call.

func greet(person name: String) {
    print("Hello, \(name)")
}

greet("Ava")

Fix: Use the required label exactly as the function declaration defines it.

func greet(person name: String) {
    print("Hello, \(name)")
}

greet(person: "Ava")

The corrected version works because the call matches the function's required external parameter name.

Mistake 2: Using the internal parameter name at the call site

Beginners often confuse the internal parameter name with the argument label. Only the external label belongs in the function call.

Problem: This code uses the local name name instead of the external label person, which causes an error such as Incorrect argument label in call or Extraneous argument label depending on the declaration.

func greet(person name: String) {
    print("Hello, \(name)")
}

greet(name: "Ava")

Fix: Call the function with the external label and reserve the internal name for use inside the function body.

func greet(person name: String) {
    print("Hello, \(name)")
}

greet(person: "Ava")

The corrected version works because Swift distinguishes between the call-site label and the local parameter name.

Mistake 3: Supplying a label when the function uses an underscore

An underscore means the argument has no label at the call site. If you add one anyway, the call does not match the function declaration.

Problem: This function explicitly omits the first label, so using one causes an error such as Extraneous argument label 'number:' in call.

func square(_ number: Int) -> Int {
    return number * number
}

let result = square(number: 5)

Fix: Remove the label when the parameter is declared with an underscore.

func square(_ number: Int) -> Int {
    return number * number
}

let result = square(5)

The corrected version works because the call matches the unlabeled parameter definition.

Mistake 4: Assuming a default value makes the parameter optional

A parameter with a default value can be omitted, but its type is still whatever the function declares. It is not automatically an optional type.

Problem: This code treats isAdmin as though it were a Bool?, but the parameter type is still Bool.

func createUser(name: String, isAdmin: Bool = false) {
    if isAdmin == nil {
        print("No admin value provided")
    }
}

Fix: Use the parameter as its declared type. If you truly need nil as a distinct state, declare an optional parameter instead.

func createUser(name: String, isAdmin: Bool = false) {
    if isAdmin {
        print("Create admin user for \(name)")
    } else {
        print("Create regular user for \(name)")
    }
}

The corrected version works because default values provide fallback behavior without changing the parameter's type.

7. Best Practices

Use labels to make calls read like clear phrases

The best argument labels improve readability at the call site. Favor labels that explain the role of the value.

// Less clear
func transfer(_ amount: Double, _ account: String) {
    print("Transfer \(amount) to \(account)")
}

// Preferred
func transfer(amount: Double, to account: String) {
    print("Transfer \(amount) to \(account)")
}

The preferred version is easier to understand because the call explains what each value means.

Choose default values only for genuinely common cases

A default value should represent the normal behavior, not a surprising shortcut.

// Less helpful if most calls override it
func saveReport(format: String = "xml") {
    print("Saving as \(format)")
}

// Better if this is the real common case
func saveReport(format: String = "pdf") {
    print("Saving as \(format)")
}

This matters because defaults should reduce work, not force callers to keep overriding a poor choice.

Do not remove labels unless the meaning is obvious

Using _ can make function calls shorter, but too many unlabeled arguments make code harder to read.

// Less preferred
func move(_ x: Int, _ y: Int) {
    print("Move to \(x), \(y)")
}

// Preferred
func move(toX x: Int, y yValue: Int) {
    print("Move to \(x), \(yValue)")
}

The preferred version gives more context, especially when many calls appear across a large codebase.

8. Limitations and Edge Cases

9. Practical Mini Project

Let’s build a small notification helper that uses both argument labels and default values. This is a realistic example because notifications often need a required message plus a few optional settings.

func sendNotification(to user: String, message: String, priority: String = "normal", shouldLog: Bool = true) {
    let finalMessage = "[\(priority.uppercased())] To \(user): \(message)"
    print(finalMessage)
    
    if shouldLog {
        print("Notification logged.")
    }
}

sendNotification(to: "Ava", message: "Your order has shipped.")
sendNotification(to: "Noah", message: "Server restart at 9 PM.", priority: "high")
sendNotification(to: "Mia", message: "Draft saved.", shouldLog: false)

This function uses:

The result is an API that is short for normal use and still flexible for special cases.

10. Key Points

11. Practice Exercise

Create a function named scheduleMeeting with these rules:

Expected output: Two printed lines describing meetings, one with a 30-minute duration and one with your custom duration.

Hint: Use one external name and one local name for the first parameter, and remember that the default value belongs in the function declaration.

func scheduleMeeting(with person: String, at: String, duration: Int = 30) {
    print("Meeting with \(person) at \(at) for \(duration) minutes.")
}

scheduleMeeting(with: "Taylor", at: "10:00 AM")
scheduleMeeting(with: "Chris", at: "2:00 PM", duration: 45)

12. Final Summary

Swift argument labels and default values are small features with a big effect on code quality. Argument labels make function calls easier to read by describing what each value means, while default values reduce repetition by allowing common arguments to be omitted.

You also saw an important distinction: the label used in a function call is not always the same as the local parameter name inside the function, and a default value does not turn a parameter into an optional. Those details explain many beginner errors such as missing labels, extraneous labels, and confusion about parameter types.

As a next step, practice writing your own utility functions and focus on how they read at the call site. After that, a useful follow-up topic is Swift function overloading and parameter naming, because it builds directly on the design ideas you learned here.