A method can return an updated copy instead of changing the original value.

Build an updated value

selectedLevel
returned_copy.swift
Replay: real traced execution (multi-file project)
struct Settings {
    var level: Int

    func withLevel(_ nextLevel: Int) -> Settings {
        var copy = self
        copy.level = nextLevel
        return copy
    }
}

let selectedLevel = 2
let base = Settings(level: 0)
let updated = base.withLevel(selectedLevel)
let message = "base=\(base.level), updated=\(updated.level)"

print(message)
struct Settings {
    var level: Int

    func withLevel(_ nextLevel: Int) -> Settings {
        var copy = self
        copy.level = nextLevel
        return copy
    }
}

let selectedLevel = 1
let base = Settings(level: 0)
let updated = base.withLevel(selectedLevel)
let message = "base=\(base.level), updated=\(updated.level)"

print(message)
struct Settings {
    var level: Int

    func withLevel(_ nextLevel: Int) -> Settings {
        var copy = self
        copy.level = nextLevel
        return copy
    }
}

let selectedLevel = 4
let base = Settings(level: 0)
let updated = base.withLevel(selectedLevel)
let message = "base=\(base.level), updated=\(updated.level)"

print(message)
  1. selectedLevel ← 2, base ← Settings(level: 0)

    11let selectedLevel→ 2 = 2  //@selectedLevel=1, 412let base→ Settings(level: 0) = Settings(level: 0)13let updated = baseSettings(level: 0).withLevel(selectedLevel2)14let message = "base=\(base.level), updated=\(updated.level)"
  2. copy ← Settings(level: 0), copy.level ← 2

    4func withLevel(_ nextLevel2: Int) -> Settings {5    var copy→ Settings(level: 0) = self6    copy.level→ 2 = nextLevel27    return copySettings(level: 2)8}
  3. updated ← Settings(level: 2), message ← base=0, updated=2

    12let base = Settings(level: 0)13let updated→ Settings(level: 2) = baseSettings(level: 0).withLevel(selectedLevel2)14let message→ base=0, updated=2 = "base=\(base.level0), updated=\(updated.level2)"1516print(messagebase=0, updated=2)
    outputbase=0, updated=2
  1. selectedLevel ← 1, base ← Settings(level: 0)

    11let selectedLevel→ 1 = 112let base→ Settings(level: 0) = Settings(level: 0)13let updated = baseSettings(level: 0).withLevel(selectedLevel1)14let message = "base=\(base.level), updated=\(updated.level)"
  2. copy ← Settings(level: 0), copy.level ← 1

    4func withLevel(_ nextLevel1: Int) -> Settings {5    var copy→ Settings(level: 0) = self6    copy.level→ 1 = nextLevel17    return copySettings(level: 1)8}
  3. updated ← Settings(level: 1), message ← base=0, updated=1

    12let base = Settings(level: 0)13let updated→ Settings(level: 1) = baseSettings(level: 0).withLevel(selectedLevel1)14let message→ base=0, updated=1 = "base=\(base.level0), updated=\(updated.level1)"1516print(messagebase=0, updated=1)
    outputbase=0, updated=1
  1. selectedLevel ← 4, base ← Settings(level: 0)

    11let selectedLevel→ 4 = 412let base→ Settings(level: 0) = Settings(level: 0)13let updated = baseSettings(level: 0).withLevel(selectedLevel4)14let message = "base=\(base.level), updated=\(updated.level)"
  2. copy ← Settings(level: 0), copy.level ← 4

    4func withLevel(_ nextLevel4: Int) -> Settings {5    var copy→ Settings(level: 0) = self6    copy.level→ 4 = nextLevel47    return copySettings(level: 4)8}
  3. updated ← Settings(level: 4), message ← base=0, updated=4

    12let base = Settings(level: 0)13let updated→ Settings(level: 4) = baseSettings(level: 0).withLevel(selectedLevel4)14let message→ base=0, updated=4 = "base=\(base.level0), updated=\(updated.level4)"1516print(messagebase=0, updated=4)
    outputbase=0, updated=4
copied update Returning a modified copy keeps the original value available for comparison.