はじめに

KVOとはKey-Value Observingの略で、Objective-Cの時代からあるCoCoaフレームワークの基本的な機能です。フレームワークとしてはFoundationに含まれ、Notificationsに分類されています。

Swift4から新しい関数やclassが導入されているようなので紹介いたします。

クロージャ記述

まず、KVOがクロージャで記述できるようになりました。
自分的にはKVOって何か複雑な感じがしていたのですが、クロージャに対応しただけで何か一気に分かりやすくなった気がします(笑)

func observe<Value>(_ keyPath: KeyPath<T, Value>, options: NSKeyValueObservingOptions = default, changeHandler: @escaping (T, NSKeyValueObservedChange<Value>) -> Void) -> NSKeyValueObservation

サンプル

例としてUIScrollViewのcontentOffsetに変化があった場合に設定されたクロージャを呼び出すコードを挙げます。

Swift

    // observeの結果を格納
    private var keyValueObservations = [NSKeyValueObservation]()

    // UIScrollViewの移動を感知してclosureを実行する
    private func addKVO(scrollView: UIScrollView, _ closure: @escaping ()->Void)
    {
        let keyValueObservation = scrollView.observe(\.contentOffset, options: [.new, .old])
        { _, change in
            if change.newValue == nil
            {
                return
            }
            closure() // キーボードを消すとか・・・
        }
        keyValueObservations.append(keyValueObservation)
    }

    // NSKeyValueObservation配列に格納したKVOを停止する
    private func removeKVO()
    {
        for keyValueObservation in keyValueObservations
        {
            keyValueObservation.invalidate()
        }
        keyValueObservations.removeAll()
    }

observeしたいオブジェクトに対してobserve関数を呼び出すだけです。プロパティの記述で\を入れているのはエスケープの意味なのかどうか分かりませんがAppleのソースではこのような記載になって居ます。
optionsは従来通り.newで新しい値を取得します。.oldをつけると変更前の値を取得できます。
クロージャ内の最初の引数が自分のインスタンスオブジェクトで、二番目が変更された値です。

NSKeyValueObservationクラスはほぼ説明がないのですが、コードのようにobserve処理を保持できるようです。

そもそもどこで使うか

KVOの使い所ですが、これは今回のobserve関数に限ったことではありません。
ですが、あえてここで書いておくと、KVOはプログラムコードの疎結合の実現するためにはかなり有効だと思います。

例えばUIScrollViewのdelegateプロパティは通常はArrayではないなので

Swift
var delegate: UIScrollViewDelegate?

監視者は1つのオブジェクトに限られます。しかしこの制約はやっかいで、例えばサンプルのようなUIScrollViewの移動監視をライブラリーとして分離したい場合は、本コード側が保持しているUIScrollViewインスタンスのdelegateを勝手に使用するわけにはいきません。
そのような場合は本コード側のUIScrollViewDelegate実装からライブラリに変更通知を行う必要があるのですが、なんだか疎結合のために関数やコードが増えていっています。シンプルさが損なわれてしまいます。

そこでライブラリ側でKVOを使うとしたらどうでしょうか。
ライブラリ側にはUIScrollViewインスタンスを渡すだけで済みます。監視はライブラリ内でobserve関数を呼び出すだけです。

もともとはUIScrollViewのUIScrollViewDelegateのインスタンスをひとつしか登録できないのが問題なのですが、使いやすさを考慮するとこれは致し方ないでしょう。なのでもう一段階踏み込んでライブラリなどを整備していく場合はKVOを利用することは大きなメリットがあると考えています。

補足

解説記事がないか調べてみたのですが、2017年12月19日現在では

国内で見つかった記事はクラスメソッドさんの
[iOS 11] Swift 4は前バージョンから何が変わったか比較した
がobserve関数に触れているだけです。

Using Swift with Cocoa and Objective-C (Swift 4.0.3)
https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/AdoptingCocoaDesignPatterns.html
あたりには記述例が出ています。

またBuildできるサンプルとしては、
https://developer.apple.com/library/content/samplecode/AVCam/Introduction/Intro.html
があります。