Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Why doesn't didSet work?

In many examples of didSet I see on SO, this code will return 0, however, I can't get it to return anything other than the original value. What am I doing wrong?

Swift

struct Circle {
    var radius: Double {
        didSet {
            if radius < 0 {
                radius = 0
            }
        }
    }
}

var circ = Circle(radius: -25)

print(circ.radius)

Output

-25
like image 323
nipponese Avatar asked Jan 30 '16 01:01

nipponese


3 Answers

didSet isn't called during initialization, only afterwards. If you want to validate data during initialization, your initializer should do it.

If you add:

circ.radius = -50
print(circ.radius)

you'll see it working as you'd expect, and the output will be 0.0.

like image 175
Crowman Avatar answered Sep 28 '22 07:09

Crowman


You can make sure didSet in the init, if you put it in a defer statement. Also works in deinit.

class Circle {
    var radius: Double {
       didSet {
          if radius < 0 {
             radius = 0
          }
       }
    }

    init(radius: Double) {
        defer { self.radius = radius }
    }
}
like image 23
Dan Morrow Avatar answered Sep 28 '22 07:09

Dan Morrow


As written by Paul in the comments, property observers didSet and willSet are not called during value initialization.

If you want to call them for a value also on initialization, you could add a function call to re-set the radius property after it has been initially set in the initializer:

struct Circle {
    var radius: Double {
        didSet {
            if radius < 0 {
                radius = 0
            }
        }
    }

    init(radius: Double) {
        self.radius = radius
        setRadius(radius) // <-- this will invoke didSet
    }

    mutating func setRadius(radius: Double) {
        self.radius = radius
    }
}

var circ = Circle(radius: -25)

print(circ.radius) // 0.0
like image 39
dfrib Avatar answered Sep 28 '22 07:09

dfrib