-
Notifications
You must be signed in to change notification settings - Fork 1.3k
/
Copy pathPersistedProperty.swift
72 lines (64 loc) · 2.75 KB
/
PersistedProperty.swift
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
//
// PersistedProperty.swift
// Loop
//
// Created by Pete Schwamb on 5/29/22.
// Copyright © 2022 LoopKit Authors. All rights reserved.
//
import Foundation
import os.log
@propertyWrapper public struct PersistedProperty<Value> {
let key: String
let storageURL: URL
private let log = OSLog(subsystem: "com.loopkit.Loop", category: "PersistedProperty")
public init(key: String, shared: Bool = false) {
self.key = key
let documents: URL
if shared {
let appGroup = Bundle.main.appGroupSuiteName
guard let directoryURL = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: appGroup) else {
preconditionFailure("Could not get a container directory URL. Please ensure App Groups are set up correctly in entitlements.")
}
documents = directoryURL.appendingPathComponent("com.loopkit.LoopKit", isDirectory: true)
} else {
guard let localDocuments = try? FileManager.default.url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true) else {
preconditionFailure("Could not get a documents directory URL.")
}
documents = localDocuments
}
storageURL = documents.appendingPathComponent(key + ".plist")
}
public var wrappedValue: Value? {
get {
do {
let data = try Data(contentsOf: storageURL)
os_log(.info, "Reading %{public}@ from %{public}@", key, storageURL.absoluteString)
guard let value = try PropertyListSerialization.propertyList(from: data, options: [], format: nil) as? Value else {
os_log(.error, "Unexpected type for %{public}@", key)
return nil
}
return value
} catch {
os_log(.error, "Error reading %{public}@: %{public}@", key, error.localizedDescription)
}
return nil
}
set {
guard let newValue = newValue else {
do {
try FileManager.default.removeItem(at: storageURL)
} catch {
os_log(.error, "Error deleting %{public}@: %{public}@", key, error.localizedDescription)
}
return
}
do {
let data = try PropertyListSerialization.data(fromPropertyList: newValue, format: .binary, options: 0)
try data.write(to: storageURL, options: .atomic)
os_log(.info, "Wrote %{public}@ to %{public}@", key, storageURL.absoluteString)
} catch {
os_log(.error, "Error saving %{public}@: %{public}@", key, error.localizedDescription)
}
}
}
}