Swift Programming: getter/setter in stored property

IosSwift

Ios 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”

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionbohanlView Question on Stackoverflow
Solution 1 - IosMihai FratuView Answer on Stackoverflow
Solution 2 - IosJoseph MarkView Answer on Stackoverflow
Solution 3 - Iosuser3675131View Answer on Stackoverflow
Solution 4 - IosJim DriscollView Answer on Stackoverflow
Solution 5 - IosMike RapadasView Answer on Stackoverflow