Quantcast
Viewing all articles
Browse latest Browse all 12

Answer by dfrib for What is the purpose of willSet and didSet in Swift?

The many well-written existing answers cover the question well, but I'll mention, in some detail, an addition that I believe is worth covering.


The willSet and didSet property observers can be used to call delegates, e.g., for class properties that are only ever updated by user interaction, but where you want to avoid calling the delegate at object initialization.

I'll cite Klaas up-voted comment to the accepted answer:

willSet and didSet observers are not called when a property is first initialized. They are only called when the property’s value is set outside of an initialization context.

This is a quite neat as it means e.g. the didSet property is a good choice of launch point for delegate callbacks & functions, for your own custom classes.

As an example, consider some custom user control object, with some key property value (e.g. position in rating control), implemented as a subclass of UIView:

// CustomUserControl.swiftprotocol CustomUserControlDelegate {    func didChangeValue(value: Int)    // func didChangeValue(newValue: Int, oldValue: Int)    // func didChangeValue(customUserControl: CustomUserControl)    // ... other more sophisticated delegate functions}class CustomUserControl: UIView {    // Properties    // ...    private var value = 0 {        didSet {            // Possibly do something ...            // Call delegate.            delegate?.didChangeValue(value)            // delegate?.didChangeValue(value, oldValue: oldValue)            // delegate?.didChangeValue(self)        }    }    var delegate: CustomUserControlDelegate?    // Initialization    required init?(...) {         // Initialise something ...        // E.g. 'value = 1' would not call didSet at this point    }    // ... some methods/actions associated with your user control.}

After which your delegate functions can be used in, say, some view controller to observe key changes in the model for CustomViewController, much like you'd use the inherent delegate functions of the UITextFieldDelegate for UITextField objects (e.g. textFieldDidEndEditing(...)).

For this simple example, use a delegate callback from the didSet of the class property value to tell a view controller that one of it's outlets have had associated model update:

// ViewController.swiftImport UIKit// ...class ViewController: UIViewController, CustomUserControlDelegate {    // Properties    // ...    @IBOutlet weak var customUserControl: CustomUserControl!    override func viewDidLoad() {        super.viewDidLoad()        // ...        // Custom user control, handle through delegate callbacks.        customUserControl = self    }    // ...    // CustomUserControlDelegate    func didChangeValue(value: Int) {        // do some stuff with 'value' ...    }    // func didChangeValue(newValue: Int, oldValue: Int) {        // do some stuff with new as well as old 'value' ...        // custom transitions? :)    //}    //func didChangeValue(customUserControl: CustomUserControl) {    //    // Do more advanced stuff ...    //}}

Here, the value property has been encapsulated, but generally: in situations like these, be careful not to update the value property of the customUserControl object in the scope of the associated delegate function (here: didChangeValue()) in the view controller, or you'll end up with infinite recursion.


Viewing all articles
Browse latest Browse all 12

Trending Articles