I think that Java got this one right. (I do not at all like the cargo cult custom of getter/setter methods for fields; I'm referring to the language only.)
In Java (and JS) there's a separate, all-knowing garbage collector, while swift is reference counted. In an ARC runtime, the didSet/willSet distinction avoids explicit calls to release the object, which is pretty clearly a good thing on the programmer's end. You can debate whether the benefits of full garbage collectors outweigh their performance characteristics, but given ARC, the didSet/willSet distinction definitely makes sense.
In this scenario it's easy to make the old method do something sensible like "return the first item." But maintaining an old field is more difficult: you can't make it lazy, you can't eliminate its backing storage, etc.
Scala does this quite transparent. Something defined as a `var` (variable), `val` (immutable variable), `lazy val` (lazy immutable variable) or `def` (method) is called source- and binary compatible from the caller side.
I've never seen this trick anyone, except for maybe unexpected bad performance.
If you write a property (what other languages might call a "field") then by default it's a stored property, i.e. it's backed by a bit of memory in the object. If you need to take actions on changes, you can implement a willSet or didSet handler to do so. If you need to change how the value is stored and retrieved altogether, you can change it to a computed property, which invokes code to get and set rather than reading and writing to a chunk of memory. All of this is completely transparent to the caller.
It's particularly interesting because it still acts like a mutable value. You can still pass a reference to such a field into an inout parameter using &, or call mutating methods on it. Behind the scenes, the compiler does a read/modify/write dance rather than mutating the value in place.