KVO
概要
KVO は、簡潔に言うと、あるオブジェクトが自身のプロパティの変更を他のオブジェクトに通知するための仕組みを提供するメカニズムである。典型的な Observerパターン のような仕組みだけれど、追加の実装を必要とせずに簡単にプロパティの監視ができる。 code:swift
class MyObject: NSObject {
@objc dynamic var observableProperty: NSDate
// ...
}
基本的には、以下の手順でプロパティの監視を開始する。
登録しても、Observer は監視対象オブジェクトから強参照されないので注意 Observer が解放される前に解除しておく必要がある
監視の開始
KVO で値を監視するには、まず addObserver で監視を開始する必要がある。 code:swift
func addObserver(_ observer: NSObject,
forKeyPath keyPath: String,
options: NSKeyValueObservingOptions = [],
context: UnsafeMutableRawPointer?)
変更前の値は .old, 変更後の値は .new を指定すると、各々キー newKey, oldKey に値が格納されて返ってくる。変更前後の両方の値が欲しい場合は .old | .new のように OR でつなぐ。監視後に初期値を通知させたい場合は .initial、プロパティが実際に変更される前後で通知が欲しい場合は .prior を指定する。
通知の受け取り
change Dictionary には、指定した option に対応した値以外にも情報が格納されている。 KVO におけるプロパティ監視では、値の「変更」とは、そのプロパティの setter が呼び出されたことを示す。そのため、設定の前後でその内容に変化がなくとも通知は行われる ので、注意。 WIP
KVC (Key Value Coding)
オブジェクトのプロパティに間接的にアクセスさせる
プロパティへ間接的にアクセスできる
プロパティのアクセサや、変数自体に直接アクセスさせない
NSKeyValueCoding を実装しているオブジェクトに対しては利用できる
swift では、コンパイルやランタイムの仕様、アクセス制御等のためにさまざまなキーワードや Attribute をサポートしている 例えば、final を増やしたクラスはサブクラスが作れない
これにより、コンパイラは特別な最適化が行えるようになる
code:swift
import Foundation
class User: NSObject {
@objc var name: String
@objc var age: Int
@objc var parent: User?
override init () {
self.name = ""
self.age = 0
super.init()
}
}
let user = User()
// 直接設定
user.name = "tasuwo"
user.age = 10
// KVC
user.setValue("tarou", forKey: "name")
user.setValue(100, forKey: "age")
// KVC: KeyPath による設定
user.parent = User()
user.setValue(10, forKeyPath: "parent.age")
user.setValue("test", forKeyPath: "parent.name")
#keyPath ディレクティブを利用すると、KeyPath を コンパイル時に チェックしてくれる
Swift 4 以上からは、NSObject を必要としない KVC がある
code:swift
class Student {
var name: String = “”
var gradeLevel: Int = 0
}
let student1 = Student()
KVO (Key Value Observing)
オブジェクトのプロパティに間接的にアクセスさせる方法
プロパティのアクセさや、変数自体に直接アクセスさせない
これに対応させるためには、クラスが NSKeyValueCoding プロトコルを実装している必要がある
KVC (Key Value Coding)