It seems like the past few weeks in iOS news has been dominated by the addition of the Encodable, Decodable and Codable protocols - finally fixing the ugly problem of dealing with JSON in Swift. The deprecation of the open source libraries that simplify dealing with JSON is a good thing, and I hope the community at large can come to an agreement that we’ve found an optimal solution to the problem.
One of the most exciting additions to the Foundation library in iOS 11 that somehow flew under my radar was the new Swift syntax for key value observation. It’s long been known that the KVO API was one of the more obfuscated and confusing in Cocoa, which makes this change so exciting. Not only is it type safe, but also terse as hell:
@objcMembers class Foo: NSObject {
dynamic var string: String
override init() {
= "hotdog"
string super.init()
}
}
let foo = Foo()
// Here it is, kvo in 2 lines of code!
let observation = foo.observe(\.string) { (foo, change) in
("new foo.string: \(foo.string)")
print}
.string = "not hotdog"
foo// new foo.string: not hotdog
A couple things to note:
- In Swift 4
@objc
is no longer automatically inferred on subclasses ofNSObject
. In order to activate Objective-C’s introspective capabilities for an entire Swift class heirarchy, we need to use the new keyword@objcMembers
. This essentially re-enables@objc
inference on all subclasses and extensions ofFoo
, allowing the use of KVO. For further reading on the why of this change, I recommend taking a look at the Swift evolution proposal on the subject. - The
dynamic
keyword is required for theobserve
closure to fire after a value change. Without it,observe
will fail silently. - Notice how the key path used for key value observation is a type
safe variable of the class
Foo
. The\.string
syntax is shorthand forFoo.string
, which is the result of a new generic class introduced with iOS 11 calledKeyPath
.KeyPath
inherits fromPartialKeyPath
andAnyKeyPath
, and is what allows the transformation of what used to be an unsafe stringly typed Objective-C API, into a Swifty type safe API. - The cherry on top here is that we no longer need to remove the
observer at
deinit
, I know I’m not the only one that has been bitten by that in the past.
I’m very excited about the additions to the Foundation library in iOS 11, particularly those that ease the interoperability of writing Swift on top of the Objective-C runtime. I recommend taking the time to watch the WWDC video highlighting the addition and usage of Codable, KeyPath and the KVO related changes.