Using property observer to prevent property value going too high

Hi all. In Swift Apprentice Chapter 17 there is a section on limiting a variable using property observers. The example on page 222 limits the maximum current of a LightBulb instance to 40 using didSet:
class LightBulb {
static let maxCurrent = 40
var currentCurrent = 0 {
didSet {
if currentCurrent > LightBulb.maxCurrent {
print(“Current too high, falling back to previous setting.”)
currentCurrent = oldValue
This is fine. However, the Mini Exercise then asks us to PREVENT the value going above maxCurent using willSet (to prevent the bulb burning out). I have tried this:

class NewLightBulb {
let maxCurrent = 40
var currentCurrent = 0 {
willSet {
if newValue > maxCurrent {
print (“You can’t set current that high”)
newValue = maxCurrent

But this gives an error saying I can’t change newValue as it’s immutable.
I instead tried simply making currentCurrent = maxCurrent in that last line, but Xcode tells me “Attempting to store to property ‘currentCurrent’ within its own willSet, which is about to be overwritten by the new value”.
So how do I prevent newValue writing to the property (to prevent LightBulb current going above the upper limit)? I can’t figure out how to do it. Any help would be greatly appreciated.

1 Like

Hum, according to my own experimentation, it’s not possible to use a willSet observer to modify its property value.

But didSet does exactly what you want anyway, so is there really a problem?

See also this blog which seems to conform this…

Thanks Keith. didSet is fine for practical purposes but the Swift Apprentice mini exercise specifically asked me to do the equivalent with willSet - the idea being you wouldn’t want a light bulb’s current to exceed limits, even for a short time.

I did dig into the code supplied with the text and discovered they used an additional variable (onOff: Boolean or something like that). In the willSet, if newValue > maxCurrent, they said onOff = FALSE. Then in the didSet they reset the value back to whatever you want.

It’s a workaround but it will do. Thanks again.

Interesting, because now I’m wondering whether you would ever notice the difference between capping the value in didSet rather than willSet (which I agree, seems to be the “safer” way of doing it).

I can’t see that there is a difference in a single threaded client, because the didSet will cap the value in effectively an atomic operation; but I suppose a multithreaded client of your class might conceivably set the property to an illegal value, then read the illegal value back on another thread before the didSet method has time to cap the value. Maybe using willSet helps here. But properties aren’t thread safe anyway, so unless your class takes active measures to isolate the underlying storage onto a single thread or queue, I don’t really see how the willSet workaround adds anything.

Just IMHO - I’m learning this stuff!

Yeah I never would have pursued it except to scratch an itch because I’d been stumped. I’m obviously learning more than you - I have no idea what your comments on threads mean. I’ve been programming a long time but mostly with simple code to solve complex mathematics (think Fortran 90). This is my first venture into object oriented programming.

1 Like