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?
The issue is that enum
s 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.