← All repositories

listless

A simple list app for Apple platforms

git clone https://code.inqk.net/listless.git


Listless/Sync/KeyValueSyncBridge.swift (2040B)

1import Foundation
2
3final 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}