Search code examples
swiftenumssettercomputed-properties

Swift enum values not settable


I am adding some syntactical sugar to my app, and I came across an 'inconsistency'. There is probably good reason for it, but is there way to clean the implementation a little. I a doing this to provide a single place to set/get some properties.

enum MyType: String {
    case Unknown, First, Second

    var enabled: Bool {
        set { UserDefaults.standard.set(newValue, forKey: self.rawValue) }
        get { return UserDefaults.standard.bool(forKey: self.rawValue) }
    }

}

Now I can use the enum values to get the defaults

if MyType.First.enabled {
    ........
}

But I cannot directly set the value:

MyType.First.enabled = true

elicits 'cannot set property, First is not assignable'

but I can get away with

var type = MyType.First
type.enabled = true

Is there a simple way to use the one-line method?


Solution

  • The issue is that enums are value types, so when you call the setter of enabled on MyType.First, you mutate First as well. If you don't assign value types to a mutable variable explicitly, they are considered immutable. This is why if MyType.First.enabled {...} doesn't work, but

    var type = MyType.First
    type.enabled = true
    

    does work.

    If you mark the setter as nonmutating, the issue is resolved, since the compiler will now know that you aren't mutating a value type when calling the setter on its property.

    enum MyType: String {
        case unknown, first, second
    
        var enabled: Bool {
            nonmutating set { UserDefaults.standard.set(newValue, forKey: self.rawValue) }
            get { return UserDefaults.standard.bool(forKey: self.rawValue) }
        }
    
    }
    

    P.S.: the Swift naming convention for enum cases is lowerCamelCase, since they are not types themselves and only types should be UpperCamelCase. I've modified your MyType enum accordingly.