Swift Methods

A method is a function that lives inside a struct, class, or enum. Properties describe what an object knows, and methods describe what an object can do. A lamp has a brightness property and a turnOn method. A music player has a volume property and a play method.

Think of a TV remote. Each button triggers one action on the television. Methods work as the buttons of an object. You press a button by calling the method with a dot after the object name.

Diagram: Object With Buttons

  +---------------------------+
  |  Counter                  |
  |---------------------------|
  |  value        (property)  |
  |---------------------------|
  |  [increment]  (method)    |
  |  [reset]      (method)    |
  |  [describe]   (method)    |
  +---------------------------+

Instance Methods

An instance method belongs to one specific object and can read that object's properties directly.

struct Counter {
    var value = 0

    func describe() -> String {
        "Counter at \(value)"
    }
}

let counter = Counter()
print(counter.describe())   // Output: Counter at 0

Mutating Methods

Structs are value types, and their methods cannot change properties by default. Mark a method with mutating to allow changes. Such a method works only on variables, not constants.

struct Counter {
    var value = 0

    mutating func increment(by amount: Int = 1) {
        value += amount
    }

    mutating func reset() {
        value = 0
    }
}

var clicks = Counter()
clicks.increment()
clicks.increment(by: 5)
print(clicks.value)   // Output: 6

clicks.reset()
print(clicks.value)   // Output: 0

Classes are reference types, and their methods change properties freely. Class methods never need the mutating keyword.

The Self Keyword

Every instance owns an implicit property named self that points to the instance itself. Use it when a parameter name matches a property name.

struct Player {
    var name: String

    mutating func rename(to name: String) {
        self.name = name
    }
}

var gamer = Player(name: "Zed")
gamer.rename(to: "Nova")
print(gamer.name)   // Output: Nova

The left side self.name refers to the property. The right side name refers to the parameter.

Assigning to Self

A mutating method on a struct can replace the whole instance by assigning a fresh value to self.

struct Light {
    var isOn = false

    mutating func toggle() {
        isOn.toggle()
    }

    mutating func factoryReset() {
        self = Light()
    }
}

var lamp = Light()
lamp.toggle()
print(lamp.isOn)     // Output: true
lamp.factoryReset()
print(lamp.isOn)     // Output: false

Type Methods

A type method belongs to the type and not to an instance. Call it on the type name. Declare it with static. Classes accept class func, which subclasses may override.

struct MathHelper {
    static func square(_ number: Int) -> Int {
        number * number
    }
}

print(MathHelper.square(7))   // Output: 49

Type methods suit utilities that need no stored data, such as converters and factory builders.

Methods That Return Values

A method can return a result. The caller may ignore the result when the method carries the @discardableResult attribute.

struct Wallet {
    var balance = 100

    @discardableResult
    mutating func spend(_ amount: Int) -> Bool {
        guard amount <= balance else { return false }
        balance -= amount
        return true
    }
}

var wallet = Wallet()
wallet.spend(30)
let success = wallet.spend(500)
print(wallet.balance)   // Output: 70
print(success)          // Output: false

Method Chaining

A method that returns the object itself allows several calls in one line. Many Swift builders use this pattern to produce readable code.

struct Pizza {
    var toppings: [String] = []

    func adding(_ topping: String) -> Pizza {
        var copy = self
        copy.toppings.append(topping)
        return copy
    }
}

let order = Pizza().adding("Cheese").adding("Olives").adding("Basil")
print(order.toppings)   // Output: ["Cheese", "Olives", "Basil"]

Choosing Between Methods and Functions

A free function stands alone and works with whatever you pass in. A method belongs to a type and works with the data inside the instance. Prefer a method when the action depends on the object's own properties. Prefer a free function when the action treats all inputs equally.

Common Mistakes

Calling a mutating method on a constant struct triggers an error. Declare the instance with var when its methods change the data.

Confusing type methods with instance methods causes another frequent error. A call such as MathHelper.square(7) uses the type name. A call such as counter.describe() uses an instance.

Real-World Use

A shopping cart exposes methods such as addItem, removeItem, and total. A video player offers play, pause, and seek. Methods give each object a clear, named list of actions, and other code uses those names without knowing the internal details.

Key Takeaways

  • Methods are functions that belong to a type.
  • Struct methods that change properties need the mutating keyword.
  • The self keyword refers to the current instance.
  • Type methods use static and run on the type name.