KeyValueSyncBridge.swift (2040B)
1 import Foundation 2 3 final class KeyValueSyncBridge { 4 private let keys: Set<String> 5 private var isSyncing = false 6 7 init(keys: Set<String>) { 8 self.keys = keys 9 } 10 11 func start() { 12 let cloud = NSUbiquitousKeyValueStore.default 13 cloud.synchronize() 14 15 for key in keys { 16 if let cloudValue = cloud.object(forKey: key) { 17 isSyncing = true 18 UserDefaults.standard.set(cloudValue, forKey: key) 19 isSyncing = false 20 } 21 } 22 23 NotificationCenter.default.addObserver( 24 self, 25 selector: #selector(cloudDidChange), 26 name: NSUbiquitousKeyValueStore.didChangeExternallyNotification, 27 object: cloud 28 ) 29 30 NotificationCenter.default.addObserver( 31 self, 32 selector: #selector(defaultsDidChange), 33 name: UserDefaults.didChangeNotification, 34 object: nil 35 ) 36 } 37 38 @objc private func cloudDidChange(_ notification: Notification) { 39 guard !isSyncing else { return } 40 guard let changedKeys = notification.userInfo?[NSUbiquitousKeyValueStoreChangedKeysKey] as? [String] else { 41 return 42 } 43 let cloud = NSUbiquitousKeyValueStore.default 44 isSyncing = true 45 for key in changedKeys where keys.contains(key) { 46 UserDefaults.standard.set(cloud.object(forKey: key), forKey: key) 47 } 48 isSyncing = false 49 } 50 51 @objc private func defaultsDidChange(_ notification: Notification) { 52 guard !isSyncing else { return } 53 let defaults = UserDefaults.standard 54 let cloud = NSUbiquitousKeyValueStore.default 55 isSyncing = true 56 for key in keys { 57 let localValue = defaults.object(forKey: key) as? NSObject 58 let cloudValue = cloud.object(forKey: key) as? NSObject 59 if localValue != cloudValue { 60 cloud.set(localValue, forKey: key) 61 } 62 } 63 isSyncing = false 64 } 65 }