こんにちは。きんくまです。
Swiftでプロパティの変更をどうやったら他のオブジェクトに伝えられるか調べてました。
例えばこんな感じのライブラリもあるみたいです。
あとは、NSObjectのサブクラスにして、KVOするやつ(Apple公式のObjective-Cの移行ガイドみたいな)
だけど、swiftにはプロパティの変更をするときにwillSet, didSetというものを呼び出す仕組みがすでにあります。
だからこいつを使ってあげれば、簡単にできるのではないかと。
で、1つプロトコルを作ってみました
protocol PropertyChangeProtocol: class{ func willSetProperty(name:String, sender:AnyObject, newValue:AnyObject!, oldValue:AnyObject!) func didSetProperty(name:String, sender:AnyObject, value:AnyObject!) }
willSetPropertyの方では
name: 変更のあったプロパティ名
sender: 出したインスタンスの参照
newValue: 新しい値
oldValue: 古い値
didSetPropertyの法では
name: 変更のあったプロパティ名
sender: 出したインスタンスの参照
value: 新しい値
がわかります。これでとりあえずの情報としては足りるかなーと。
プロトコル名のうしろに :classというのがくっついているのですが、使い方のところで弱参照のweakキーワードを使いたいからです。ないとエラーになっちゃいました。
>> How can I make a weak protocol reference in ‘pure’ Swift (w/o @objc)
こいつを使ってdelegateパターンでやってみると、
import UIKit protocol PropertyChangeProtocol: class{ func willSetProperty(name:String, sender:AnyObject, newValue:AnyObject!, oldValue:AnyObject!) func didSetProperty(name:String, sender:AnyObject, value:AnyObject!) } class Person{ weak var delegate:PropertyChangeProtocol! var age:Int = 25{ willSet{ delegate?.willSetProperty("age", sender: self, newValue:newValue, oldValue: self.age) } didSet{ delegate?.didSetProperty("age", sender:self, value:self.age) } } } class Client:PropertyChangeProtocol{ var taro:Person! init(){ taro = Person() println("taro's age is \(taro.age)") taro.delegate = self taro.age = 12 } func willSetProperty(name:String, sender:AnyObject,newValue: AnyObject!, oldValue: AnyObject!) { println("will change => name: \(name), sender: \(sender), new: \(newValue), old: \(oldValue)") } func didSetProperty(name:String, sender:AnyObject, value: AnyObject!) { println("did change => name: \(name), sender: \(sender), value: \(value)") if taro === sender { println("wow! sender is equal to taro") } } } let c = Client()
出力
taro's age is 25 will change => name: age, sender: __lldb_expr_236.Person, new: 12, old: 25 did change => name: age, sender: __lldb_expr_236.Person, value: 12 wow! sender is equal to taro
という感じです。
課題
protocolでメソッドを全部必須にしないでoptionalにしたいときは、@objcというキーワードが必要。
-> でもそれって純粋なswiftじゃないし、、。
>> Optional Protocol Requirements
複数の監視オブジェクトがもし必要になった場合に、delegateパターンだと実装が毎回面倒くさそう
-> delegateを配列にして、ループで全部のdelegateのprotocolメソッドを呼び出すっていうのはちょっと大変。1つのプロパティならいいけど、いくつもプロパティがあった場合に。小さなライブラリを作る?
■ 自作iPhoneアプリ 好評発売中!
・フォルメモ - シンプルなフォルダつきメモ帳
・ジッピー電卓 - 消費税や割引もサクサク計算!
■ LINEスタンプ作りました!
毎日使える。とぼけたウサギ