How do I overwrite the setter of stored property in Swift?
In Obj-C, I can overwrite its setter, but Swift doesn't seem to be happy about getter/setters being used for stored property.
Say I have a Card
class with a property called rank
. I don't want the client to give it any invalid value, therefore, in objective-C, I can overwrite setRank
so that it performs additional check. But willSet
in Swift doesn't seem to help because newValue
is constant and it makes no sense to assign rank
because setter will be called in a loop.
Working With Computed Properties in Swift To create computed properties, Swift offers you a getter and (an optional) setter method to work with. A getter method is used to perform a computation when requested. A setter method is an optional method. It can be used to modify a related property.
Stored Properties A stored property is a property whose value is stored as part of the instance of a particular type. Stored properties can be either variable or constant. We can use var to create a variable stored property, and let to create a constant stored property.
In willSet Swift provides your code with a special value called newValue that contains what the new property value is going to be, and in didSet you are given oldValue to represent the previous value.
Ok. Reading through Apples documentation on Swift I found this:
If you assign a value to a property within its own didSet observer, the new value that you assign will replace the one that was just set.
So all you have to do is this:
var rank: Int = 0 {
didSet {
// Say 1000 is not good for you and 999 is the maximum you want to be stored there
if rank >= 1000 {
rank = 999
}
}
}
You can't override get
/set
for a stored property but you can use property observers willSet
/didSet
:
var totalSteps: Int = 0 {
willSet(newTotalSteps) {
println("About to set totalSteps to \(newTotalSteps)")
}
didSet {
if totalSteps > oldValue {
println("Added \(totalSteps - oldValue) steps")
}
}
}
The default parameter names are newValue
for willSet
and oldValue
for didSet
, or you can name them yourself as in willSet(newTotalSteps)
.
get and set are for computed properties (they don't have any backing store). (In my opinion, the keyword 'var' is confusing here)
If you don't want to use didSet, which has the problem that the property's value is temporarily wrong, you should wrap a computed property around it.
private var _foo:Int = 0
var foo:Int {
get {
return _foo
}
set {
if(newValue > 999) {
_foo = 999
} else {
_foo = newValue
}
}
}
Or:
private var _foo:Int = 0
var foo:Int {
get {
return _foo
}
set {
guard newValue <= 999 else {
_foo = 999
return
}
_foo = newValue
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With