Swift Property Observers
By the 1930’s, Rube Goldberg had become a household name, synonymous with the fantastically complicated and whimsical inventions depicted in comic strips like “Self-Operating Napkin.” Around the same time, Albert Einstein popularized the phrase “spooky action at a distance” in his critique of the prevailing interpretation of quantum mechanics by Niels Bohr.
Nearly a century later, modern software development has become what might be seen as the quintessence of a Goldbergian contraption — sprawling ever closer into that spooky realm by way of quantum computers.
As software developers, we’re encouraged to reduce action-at-a-distance in our code whenever possible. This is codified in impressive-sounding guidelines like the Single Responsibility Principle, Principle of Least Astonishment, and Law of Demeter. Yet despite their misgivings about code that produces side effects, there are sometimes occasions where such techniques may clarify rather than confound.
Such is the focus of this week’s article about property observers in Swift, which offer a built-in, lightweight alternative to more formalized solutions like model-view-viewmodel (MVVM) functional reactive programming (FRP).
There are two kinds of properties in Swift: stored properties, which associate state with an object, and computed properties, which perform a calculation based on that state. For example,
struct S {
    // Stored Property
    var stored: String = "stored"
    // Computed Property
    var computed: String {
        return "computed"
    }
}
When you declare a stored property,
                you have the option to define property observers
                with blocks of code to be executed when a property is set.
                The will observer runs before the new value is stored
              and the did observer runs after.
            And they run regardless of whether the old value is equal to the new value.
struct S {
    var stored: String {
        willFor example, running the following code prints the resulting text to the console:
var s = S(stored: "first")
s.stored = "second"
- willSet was called
- stored is now equal to first
- stored will be set to second
- didSet was called
- stored is now equal to second
- stored was previously set to first
Swift property observers have been part of the language from the very beginning. To better understand why, let’s take a quick look at how things work in Objective-C:
Properties in Objective-C
In Objective-C, all properties are, in a sense, computed. Each time a property is accessed through dot notation, the call is translated into an equivalent getter or setter method invocation. This, in turn, is compiled into a message send that executes a function that reads or writes an instance variable.
// Dot accessor
person.name = @"Johnny";
// ...is equivalent to
[person setSide effects are something you generally want to avoid in programming because they make it difficult to reason about program behavior. But many Objective-C developers had come to rely on the ability to inject additional behavior into getter or setter methods as needed.
Swift’s design for properties formalized these patterns
            and created a distinction between side effects
            that decorate state access (stored properties)
            and those that redirect state access (computed properties).
            For stored properties, the will and did observers
        replace the code that you’d otherwise include alongside ivar access.
        For computed properties, the get and set accessors
        replace code that you might implement for @dynamic properties in Objective-C.
As a result, we get more consistent semantics and better guarantees about mechanisms like Key-Value Observing (KVO) and Key-Value Coding (KVC) that interact with properties.
So what can you do with property observers in Swift? Here are a couple ideas for your consideration:
Validating / Normalizing Values
Sometimes you want to impose additional constraints on what values are acceptable for a type.
For example, if you were developing an app that interfaced with a government bureaucracy, you’d need to ensure that the user wouldn’t be able to submit a form if it was missing a required field, or contained an invalid value.
If, say,
        a form required that names use capital letters without accents,
        you could use the did property observer
      to automatically strip diacritics and uppercase the new value:
var name: String? {
    didSetting a property in the body of an observer (fortunately)
      doesn’t trigger additional callbacks,
      so we don’t create an infinite loop here.
      This is the same reason why this won’t work as a will observer;
    any value set in the callback is immediately overwritten
    when the property is set to its new.
While this approach can work for one-off problems, repeat use like this is a strong indicator of business logic that could be formalized in a type.
A better design would be to create a Normalized type
that encapsulates the requirements of text to be entered in such a form:
struct NormalizedA failable or throwing initializer
  can surface errors to the caller
  in a way that a did observer can’t.
Now, when a troublemaker like
Jøhnny
from Llanfairpwllgwyngyllgogerychwyrndrobwllllantysiliogogogoch
comes a’knocking,
we can give him what’s for!
(Which is to say,
communicate errors to him in a reasonable manner
rather than failing silently or allowing invalid data)
Propagating Dependent State
Another potential use case for property observers is propagating state to dependent components in a view controller.
Consider the following example of a Track model
  and a Track that presents it:
struct Track {
    var title: String
    var audioWhen the track property of the view controller is set,
  the following happens automatically:
- Any previous track’s audio is paused
- The titleof the view controller is set to the new track title
- The new track’s audio is loaded and played
Pretty cool, right?
You could even cascade this behavior across multiple observed properties a la that one scene from Mousehunt.
As a general rule, side effects are something to avoid when programming, because they make it difficult to reason about complex behavior. Keep that in mind the next time you reach for this new tool.
And yet, from the tippy top of this teetering tower of abstraction, it can be tempting — and perhaps sometimes rewarding — to embrace the chaos of the system. Always following the rules is such a Bohr.