|
99 | 99 |
|
100 | 100 | public func load( |
101 | 101 | initialValue: Value?, |
102 | | - didReceive callback: @escaping (Result<Value?, any Error>) -> Void |
| 102 | + didReceive callback: @escaping @Sendable (Result<Value?, any Error>) -> Void |
103 | 103 | ) { |
104 | 104 | do { |
105 | 105 | if let initialValue, !storage.fileExists(url) { |
106 | 106 | try storage.createDirectory(url.deletingLastPathComponent(), true) |
107 | | - try save(initialValue, immediately: true) |
108 | | - callback(.success(nil)) |
| 107 | + save(initialValue, immediately: true) { result in |
| 108 | + switch result { |
| 109 | + case let .failure(error): |
| 110 | + callback(.failure(error)) |
| 111 | + case .success: |
| 112 | + callback(.success(nil)) |
| 113 | + } |
| 114 | + } |
109 | 115 | return |
110 | 116 | } |
111 | 117 | try callback(.success(decode(storage.load(url)))) |
|
117 | 123 | private func save(data: Data, url: URL, modificationDates: inout [Date]) throws { |
118 | 124 | try self.storage.save(data, url) |
119 | 125 | if let modificationDate = try storage.attributesOfItemAtPath(url.path)[.modificationDate] |
120 | | - as? Date |
| 126 | + as? Date |
121 | 127 | { |
122 | 128 | modificationDates.append(modificationDate) |
123 | 129 | } |
124 | 130 | } |
125 | 131 |
|
126 | | - public func save(_ value: Value, immediately: Bool) throws { |
127 | | - try state.withValue { state in |
128 | | - let data = try self.encode(value) |
129 | | - if immediately { |
130 | | - state.value = nil |
131 | | - state.workItem?.cancel() |
132 | | - state.workItem = nil |
133 | | - try self.storage.save(data, url) |
134 | | - return |
135 | | - } |
136 | | - if state.workItem == nil { |
137 | | - try save(data: data, url: url, modificationDates: &state.modificationDates) |
138 | | - |
139 | | - let workItem = DispatchWorkItem { [weak self] in |
140 | | - guard let self else { return } |
141 | | - self.state.withValue { state in |
142 | | - defer { |
143 | | - state.value = nil |
144 | | - state.workItem = nil |
| 132 | + public func save( |
| 133 | + _ value: Value, |
| 134 | + immediately: Bool, |
| 135 | + didComplete callback: @escaping @Sendable (Result<Void, any Error>) -> Void |
| 136 | + ) { |
| 137 | + do { |
| 138 | + try state.withValue { state in |
| 139 | + let data = try self.encode(value) |
| 140 | + if immediately { |
| 141 | + state.value = nil |
| 142 | + state.workItem?.cancel() |
| 143 | + state.workItem = nil |
| 144 | + try self.storage.save(data, url) |
| 145 | + callback(.success(())) |
| 146 | + return |
| 147 | + } |
| 148 | + if state.workItem == nil { |
| 149 | + try save(data: data, url: url, modificationDates: &state.modificationDates) |
| 150 | + callback(.success(())) |
| 151 | + let workItem = DispatchWorkItem { [weak self] in |
| 152 | + guard let self else { return } |
| 153 | + self.state.withValue { state in |
| 154 | + defer { |
| 155 | + state.value = nil |
| 156 | + state.workItem = nil |
| 157 | + } |
| 158 | + guard |
| 159 | + let value = state.value, |
| 160 | + let data = try? self.encode(value) |
| 161 | + else { return } |
| 162 | + callback( |
| 163 | + Result { |
| 164 | + try self.save( |
| 165 | + data: data, |
| 166 | + url: self.url, |
| 167 | + modificationDates: &state.modificationDates |
| 168 | + ) |
| 169 | + } |
| 170 | + ) |
145 | 171 | } |
146 | | - guard |
147 | | - let value = state.value, |
148 | | - let data = try? self.encode(value) |
149 | | - else { return } |
150 | | - try? self.save(data: data, url: self.url, modificationDates: &state.modificationDates) |
151 | 172 | } |
| 173 | + state.workItem = workItem |
| 174 | + storage.asyncAfter(.seconds(1), workItem) |
| 175 | + } else { |
| 176 | + state.value = value |
152 | 177 | } |
153 | | - state.workItem = workItem |
154 | | - storage.asyncAfter(.seconds(1), workItem) |
155 | | - } else { |
156 | | - state.value = value |
157 | 178 | } |
| 179 | + } catch { |
| 180 | + callback(.failure(error)) |
158 | 181 | } |
159 | 182 | } |
160 | 183 |
|
|
0 commit comments