Search code examples
swiftcomputed-properties

Bounds checking when calling computed property's setter using -=/+=


I am trying to make sure a computed property's setter only sets newValue within a certain range. The computed property's backing value is a UInt.

So what I thought I could do is use min(max(newValue, 0), UInt.max), like so:

private var _value: UInt = 100

public var value: UInt {
    get { return _value }
    set { _value = min(max(newValue, 0), UInt.max) }
}

But when I use a for loop to decrement the value using -= I throw an exception.

for _ in 0..<1000 {
   value -= 1
}

It seems this doesn't do any bounds checking. Is there a way around this?

It must be a computed property so I can't use didSet. The property is actually an alias for a value in an array of other values. The above is merely for example's sake.


Solution

  • The problem is that value -= 1 is equivalent to value = value - 1. As you can see, value - 1 has to be calculated before value can be set, so your bounds checking code never even has a chance to run. Even if it did run, it would never find a value less than 0 to bounds-check, as your property is a UInt.

    If you change your property to Int, this will work as intended, and there is even some precedent in Cocoa for using Int even in cases when negative numbers make no sense. (It will still be pointless to check against Int.max, however, for the same reason.)