Question

Objective-C would not allow you to run the following code:

myShape.origin.x = 50

This made it easy to detect changes in the origin, since someone using your class was forced to write myShape.origin = newOrigin, and thus you could easily tie in to the setter of this property.

Swift now allows you to perform the original, formerly-disallowed code. Assuming the following class structure, how would you detect the change to the origin in order to execute your own code (e.g. to update the screen)?

struct Point {
    var x = 0
    var y = 0
}

class Shape {
    var origin: Point = Point()
}

Update: Perhaps I should have been more explicit, but assume I don't want to modify the Point struct. The reason is that Shape is but one class that uses Point, there may very well be hundreds of others, not to mention that the origin is not the only way a Point may be used.

Was it helpful?

Solution

Property observers (willSet and didSet) do fire when sub-properties of that property are changed. In this case, when the x or y values of the Point structure change, that property will be set.

Here is my example playground code:

struct Point : Printable 
{
    var x = 0
    var y = 0

    var description : String {
    {
        return "(\(x), \(y))";
    }
}

class Shape
{
    var origin : Point = Point()
    {
        willSet(newOrigin)
        {
            println("Changing origin to \(newOrigin.description)!")
        }
    }
}

let circle = Shape()

circle.origin.x = 42
circle.origin.y = 77

And here is the console output:

Changing origin to (42, 0)!
Changing origin to (42, 77)!

OTHER TIPS

Doesn't this work?

class Shape {
   var origin: Point {
   willSet(aNewValueForOrigin) {
       // pre flight code
   }
   didSet(theOldValueOfOrigin) {
       // post flight code
   }
   }
}

Edit: revisited code and added name of arguments to reflect what to expect.

You can use Property Observers also works for structs

Link to the part on the ebook

class StepCounter {
    var totalSteps: Int = 0 {
    willSet(newTotalSteps) {
        println("About to set totalSteps to \(newTotalSteps)")
    }
    didSet {
        if totalSteps > oldValue  {
            println("Added \(totalSteps - oldValue) steps")
        }
    }
    }
}
let stepCounter = StepCounter()
stepCounter.totalSteps = 200
// About to set totalSteps to 200
// Added 200 steps
stepCounter.totalSteps = 360
// About to set totalSteps to 360
// Added 160 steps
stepCounter.totalSteps = 896
// About to set totalSteps to 896
// Added 536 steps

Use didSet, e.g.,

struct Point {
    var x = 0
    var y: Int = 0 {
    didSet {
        println("blah blah")
    }
    }
}

class Shape {
    var origin: Point = Point()
}

let s = Shape()

s.origin.y = 2
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top