Swift structs are immutable, so how come I can change them?

287 Views Asked by At

Structs are immutable meaning that they can't change. I must clearly misunderstand this whole concept as it seems that sometimes I do get to change the struct, and othertimes I don't.

Consider this code:

struct SomeStruct: View {
    var someProperty = ""
    
    var someComputedProperty: String {
        get { someProperty }
        set { someProperty = "a" } // WORKD
    }
    
    func someFunc() {
        someProperty = "b" // ERROR; BUT WORKS WITH mutating func
    }
    
    var body: some View {
        Button("SomeButton", action: {
            someProperty = "c" // ERROR
        })
    }
}

struct SomeOtherStruct {
    func someOtherFunct() {
        var someStruct = SomeStruct()
        
        someStruct.someProperty = "THIS WORKS"
    }
}

The only place where it's not actually allowed to change the struct is in the Button closure. Why is it sometimes allowed, and othertimes not? Or have I simply missunderstood what immutability actually implies?

1

There are 1 best solutions below

5
Simon Lundberg On

Structs aren't immutable. However, what they are something called value types which means they have implicit copying when passed to functions. If you pass a struct to a function and perform an action on the struct inside the function that mutates it, the outer version of the struct remains unchanged since the one passed to the function was in fact a copy.

Consider the following:

struct Foo {
    var value: Int
}

func bar(_ f: Foo) {
    f.value += 1
}

var f = Foo(value: 1)
bar(f)
// f.value is still 1

In order to mutate a struct inside a function you must explicitly pass it as inout:

func baz(_ f: inout Foo) {
    f.value += 1
}

baz(&f)
// f.value is now 2

Edit: note that I haven't used Swift UI and I don't really know how the behaviour of structs applies to that particular framework. This answer is about structs in Swift in the general sense.