Swift: Difference between KVO and willSet & didSet?

Viewed 1682

I have been working with willSet and didSet for a variable for a while. Its used to get notified and perform some action before and after a variable is changed.

I recently came across KVO which does similar thing, but with few more steps to setup.

  1. Is there any difference between these two approaches?
  2. Does one have any advantage over the other?
3 Answers

KVO is Objective C approach to observe properties is based on dynamic dispatch

While didSet/willSet are pure Swift methods which doesn't exist in ObjC

The latter in theory should be more efficient since Swift is trying to use static dispatch where possible for performance gains.

I'd go with ObjC approach only if you need compatibility with some ObjC dependencies or legacy code.

KVO lets you implement the common “Observer” pattern. With KVO, you can attach any number of observers to a property, at run time, without modifying the source code of the property you're observing.

Swift's willSet and didSet “observers” are essentially functions that are called before and after a property is set, and have to be written into the property's source code at compile time. They serve a very different purpose than KVO.

KVO : it is a mechanism that allows one object to observe properties of another object. KVO allows objects to be notified when the state of another object changes

willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.
Example: 
class StepCounter {
    var totalSteps: Int = 0 {
        willSet(newTotalSteps) {
            print("About to set totalSteps to \(newTotalSteps)")
        }
        didSet {
            if totalSteps > oldValue  {
                print("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
Related