Non-mutating setters

public enum TutorialType : String {
    case tutorial1
    case tutorial2
}

extension TutorialType {
    public var displayed: Bool {
        get { return UserDefaults.standard.bool(forKey: self.rawValue) }
        set { UserDefaults.standard.set(newValue, forKey: self.rawValue) }
    }
}

func showTutorial(_ type: TutorialType) {
    // 1. show the tutorial
    // ...
    // 2. set displayed to true
    type.displayed = true //cannot assign to property: 'type' is a 'let' constant
}

Hi:
As above, I have added a non-mutating compute attribute 'displayed' to TutorialType.
But when I use it in 'showTutorial(_:)' , the compiler will requires to me change type to a mutable variable. I think it should be valid to call 'type.displayed = true', is it a compiler bug? Any thoughts?

3 Likes

You can declare the setter nonmutating:

extension TutorialType {
    public var displayed: Bool {
        get { return UserDefaults.standard.bool(forKey: self.rawValue) }
        nonmutating set { UserDefaults.standard.set(newValue, forKey: self.rawValue) }
    }
}
25 Likes

Oh, I never knew this ! Thank you~

The same way you can declare the getter mutating. The rule of thumb is that the getter is nonmutating, and setter mutating by default.

5 Likes

This looks so wrong... well maybe not wrong, but more like class semantics.

It isn't unreasonable for structs to have reference-like behavior. Pointers are one obvious case.

8 Likes