5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

SwiftでKVO(Key-Value Observing)

Last updated at Posted at 2018-06-21

KVOは(Key-Value Observing)変数の値の変化を監視する仕組みです。
Swiftでは使ったことがなかったので試してみました。

ViewControllerにボタンを配置して、ボタンを押した時に変数の値を変えるテストプログラムを作成し動作確認します。

ViewControllerで監視するクラスを作成し、このインスタンス変数を監視します。

Hoge.swift
import Foundation

class Hoge : NSObject {
	@objc dynamic var count: Int = 0
}
ViewController.swift
import UIKit

class ViewController: UIViewController {

	var hoge: Hoge = Hoge()

	override func viewDidLoad() {
		super.viewDidLoad()
		
		// countを監視対象にする
		hoge.addObserver(self, forKeyPath: "count", options: [.old, .new], context: nil)
		
		hoge.count = 10
		hoge.count = 11
	}

	override func didReceiveMemoryWarning() {
		super.didReceiveMemoryWarning()
	}

	deinit {
		// countを監視対象から削除
		hoge.removeObserver(self, forKeyPath: "cout")
	}
	
	@IBAction func tapCountBugtton(sender: Any){
		print("----- tapCountBugtton")
		hoge.count += 1
		print("hoge.count : \(hoge.count)")
	}

	override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
		print("----- observeValue")
		print("object : \(String(describing: object))")
		print("keyPath : \(String(describing: keyPath))")
		print("change : \(String(describing: change))")
	}
}

ボタンをタップするとtapCountBugttonが実行されてhoge.countをインクリメントします。

### 出力結果

viewDidLoadでhoge.countに10を代入し、そのあとに11を代入しているのでobserveValueが2回呼ばれまています。
addObserverのoptionsで.oldと.newを指定しているのでchangeに新しい値と古い値が入っています。

コンソール出力
----- observeValue
object : Optional(<KvoTest.Hoge: 0x600000016bc0>)
keyPath : Optional("count")
change : Optional([__C.NSKeyValueChangeKey(_rawValue: new): 10, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 0])
----- observeValue
object : Optional(<KvoTest.Hoge: 0x600000016bc0>)
keyPath : Optional("count")
change : Optional([__C.NSKeyValueChangeKey(_rawValue: new): 11, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 10])

ボタンをタップするとtapCountBugttonが実行され、hoge.countをインクリメントしています。
hoge.countの値が変わるのでobserveValueが呼ばれます。

コンソール出力
----- tapCountBugtton
----- observeValue
object : Optional(<KvoTest.Hoge: 0x600000016bc0>)
keyPath : Optional("count")
change : Optional([__C.NSKeyValueChangeKey(_rawValue: new): 12, __C.NSKeyValueChangeKey(_rawValue: kind): 1, __C.NSKeyValueChangeKey(_rawValue: old): 11])
hoge.count : 12

Objective-Cの時代からあったKVOなので簡単に動くと思ったのですが、
ちょっとハマってしまいました。
最初、Hogeクラスのcountを下記のように定義していました。
これではKVOはうまく動きませんでした。

	var count: Int = 0

下記のようにobjc dynamicを指定すると正常に動作します。

	@objc dynamic var count: Int = 0

監視対象の変数にはdynamicの指定が必要なようです。
Swift4からobjcの指定が必要になったようです。

5
2
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
5
2

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?