Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 530
DrPhill Avatar asked Sep 04 '26 03:09

DrPhill


2 Answers

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.

like image 121
Dávid Pásztor Avatar answered Sep 06 '26 17:09

Dávid Pásztor


By adding the nonmutating keyword to the set method you are telling the compiler that the set method will not modify the enclosing type, that is the enum MyType in this case

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) }
    }
}
like image 30
Joakim Danielson Avatar answered Sep 06 '26 19:09

Joakim Danielson



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!