Swift
Mutating
Structs
Programming
iOS Development

Swift and mutating struct

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

Introduction

Swift struct types are value types, so assigning one value to another creates a copy. Because of that rule, any method that changes stored properties must be marked mutating, which tells the compiler that self will change.

Why mutating Exists

A struct method is not allowed to change properties unless Swift can prove the caller expects mutation. That is what the mutating keyword communicates. Without it, the method is treated like a read-only operation on the current value.

This fails to compile:

swift
1struct Counter {
2    var value = 0
3
4    func increment() {
5        value += 1
6    }
7}

Swift reports an error because increment() tries to modify value inside a non-mutating method.

The fix is straightforward:

swift
1struct Counter {
2    var value = 0
3
4    mutating func increment() {
5        value += 1
6    }
7}
8
9var counter = Counter()
10counter.increment()
11print(counter.value)

Once the method is marked mutating, Swift allows it to update the struct instance.

mutating Changes the Whole Value

A useful way to think about structs is that a mutating method can replace self, not only tweak one property. That matters when the operation changes several fields at once or resets the entire value.

swift
1struct Player {
2    var name: String
3    var score: Int
4
5    mutating func reset() {
6        self = Player(name: name, score: 0)
7    }
8}
9
10var player = Player(name: "Mina", score: 12)
11player.reset()
12print(player.score)

Here, reset() assigns a brand new Player to self. Swift allows that only because the method is mutating.

This behavior is one reason structs remain predictable. Mutation is explicit, and the compiler can stop accidental state changes in places that should stay read-only.

let Instances Cannot Call Mutating Methods

Even if a method is correctly declared, you still cannot call it on a constant struct value. Constants are frozen after initialization.

swift
1struct Point {
2    var x: Int
3    var y: Int
4
5    mutating func moveBy(dx: Int, dy: Int) {
6        x += dx
7        y += dy
8    }
9}
10
11let fixedPoint = Point(x: 0, y: 0)
12// fixedPoint.moveBy(dx: 2, dy: 3)

The commented line does not compile because fixedPoint was declared with let. If mutation is part of the design, store the value in a var.

swift
var point = Point(x: 0, y: 0)
point.moveBy(dx: 2, dy: 3)
print(point)

That distinction is important in SwiftUI and UIKit code. A view model or state container often needs var storage for structs that expose mutating methods.

Protocol Requirements and mutating

Protocols can also require mutating behavior. If a protocol method may change a value type, the protocol itself needs the mutating keyword.

swift
1protocol Resettable {
2    mutating func reset()
3}
4
5struct TimerState: Resettable {
6    var seconds = 30
7
8    mutating func reset() {
9        seconds = 30
10    }
11}
12
13var state = TimerState(seconds: 5)
14state.reset()
15print(state.seconds)

Classes do not need to write mutating in their implementation because classes are reference types, but the protocol still uses it so structs can conform correctly.

When a Class May Be a Better Fit

If you find yourself passing one struct instance through many layers and expecting every consumer to observe the same live changes, a class may model the problem better. Structs are strongest when copying is safe and desirable, such as coordinates, settings, or small domain models.

That does not mean mutating structs are awkward. In many cases they are the cleanest design because they keep value semantics while still allowing controlled updates. The key is to decide whether the data should behave like an independent copy or a shared reference.

Common Pitfalls

Forgetting mutating is the first problem most developers hit. If a method changes any stored property, mark it explicitly.

Another common mistake is declaring the instance with let and then wondering why the mutating method cannot be called. The method signature may be correct while the variable declaration is not.

Some code also mixes struct and class expectations. If several parts of the program need to observe the same evolving object, copying a struct can produce confusing behavior because later changes affect only one copy.

Finally, avoid adding mutating to every method by habit. Use it only when the method actually changes the value. Keeping read-only methods non-mutating makes the API easier to reason about.

Summary

  • 'mutating tells Swift that a struct method changes self.'
  • A mutating method can update properties or replace the entire value.
  • You cannot call a mutating method on a let constant.
  • Protocols that support value-type mutation should declare mutating requirements.
  • Choose a struct when copy semantics are useful, and choose a class when shared identity matters.

Related reading
Free course
Beginner
7 lessons
2 hours
Tackling System Design Interview Problems

A short course that equips you with the skills to approach system design interviews methodically.

Start the free course
Track what you have practised

A free account saves your progress, solutions and study plan across every problem on Codemia.

Interview Questions practice on Codemia

Over 8,000 real interview questions from top companies, searchable by company and role.

Browse interview questions

All Rights Reserved.