Swift Programming: getter/setter in stored property
IosSwiftIos Problem Overview
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.
Ios Solutions
Solution 1 - Ios
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
}
}
}
Solution 2 - Ios
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)
.
Solution 3 - Ios
get and set are for computed properties (they don't have any backing store). (In my opinion, the keyword 'var' is confusing here)
- willSet and didSet are called for an instance variable (Use didSet to override any changes)
- set and get are purely for computed properties
Solution 4 - Ios
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
}
}
Solution 5 - Ios
Simplified Example:
class Shape {
var sideLength: Double {
get {
return self.sideLength
}
set {
// Implement the setter here.
self.sideLength = newValue
}
}
}
Full example
Check out perimeter
in this example.
Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l
class EquilateralTriangle: NamedShape {
var sideLength: Double = 0.0
init(sideLength: Double, name: String) {
self.sideLength = sideLength
super.init(name: name)
numberOfSides = 3
}
var perimeter: Double {
get {
return 3.0 * sideLength
}
set {
sideLength = newValue / 3.0
}
}
override func simpleDescription() -> String {
return "An equilateral triagle with sides of length \(sideLength)."
}
}
var triangle = EquilateralTriangle(sideLength: 3.1, name: "a triangle")
triangle.perimeter
triangle.perimeter = 9.9
triangle.sideLength”