Swiftが1.2から2になって型のチェックが更に厳しくなりました。それによって、iCloud の Notificaiton が従来のコードだとうまく動かないことがわかりました。
iCloud にKeyValueStoreでデータを保存していて、変化をNSNotification で受け取る場合、まずどこかでNotificationCenter にAddObjectでNSUbiquitousKeyValueStoreDidChangeExternallyNotification
を登録します。
例えば、Viewdid Load であれば、
override func viewDidLoad() {
super.viewDidLoad()
// iCloudのデータに変更があった時の通知を受け取る
let center = NSNotificationCenter.defaultCenter()
center.addObserver(self,
selector: "ubiquitousDataDidChange:",
name: NSUbiquitousKeyValueStoreDidChangeExternallyNotification,
object: nil)
}
といった感じです。
そして、データ変更の処理メソッドを定義するわけですが、Swift1.2であれば、
func ubiquitousDataDidChange(notification: NSNotification) {
let store = NSUbiquitousKeyValueStore.defaultStore()
// 通知オブジェクトから渡ってくるデータを取得
if let info = notification.userInfo as? [String: [String]] {
if let keys = info[NSUbiquitousKeyValueStoreChangedKeysKey] {
for key in keys {
let num = store.doubleForKey(key)
self.label.text = "\(num)"
}
}
}
}
でOKでしたが、Swift2ではこれだと、info はいつも nil になります。
NSNotificationで渡されるuserInfoは、[NSObject: [AnyObject]] であり、[String: [String]] にキャストしようとすると、最初のデータは、
["NSUbiquitousKeyValueStoreChangeReasonKey" : Int32(0)]のようであり、nil となります。
Swift2の場合には、次のように実際に使うところでキャストするようにしないとうまく動作しません。
func ubiquitousDataDidChange(notification: NSNotification) {
let store = NSUbiquitousKeyValueStore.defaultStore()
// 通知オブジェクトから渡ってくるデータ取得
if let info = notification.userInfo {
if let keysrow = info[NSUbiquitousKeyValueStoreChangedKeysKey] {
let keys = keysrow as! [String]
for key in keys {
let num = store.doubleForKey(key)
label.text = "\(num)"
}
}
}
}