|
3 | 3 | // OpenSwiftUICore |
4 | 4 | // |
5 | 5 | // Audited for 6.5.4 |
6 | | -// Status: Blocked by DynamicPreferenceCombiner |
| 6 | +// Status: Complete |
7 | 7 | // ID: E7D4CD2D59FB8C77D6C7E9C534464C17 (SwiftUICore) |
8 | 8 |
|
9 | 9 | package import OpenAttributeGraphShims |
@@ -167,7 +167,7 @@ package struct DynamicContainer { |
167 | 167 | var outputs = _ViewOutputs() |
168 | 168 | for key in inputs.preferences.keys { |
169 | 169 | func project<K>(_ key: K.Type) where K: PreferenceKey { |
170 | | - outputs[key] = Attribute(DynamicPreferenceCombiner<K>(info: .init())) |
| 170 | + outputs[key] = Attribute(DynamicPreferenceCombiner<K>()) |
171 | 171 | } |
172 | 172 | project(key) |
173 | 173 | } |
@@ -222,21 +222,61 @@ private class DynamicAnimationListener: AnimationListener, @unchecked Sendable { |
222 | 222 | } |
223 | 223 | } |
224 | 224 |
|
225 | | -// MARK: - DynamicPreferenceCombiner [WIP] |
| 225 | +// MARK: - DynamicPreferenceCombiner |
226 | 226 |
|
227 | 227 | private struct DynamicPreferenceCombiner<K>: Rule, AsyncAttribute, CustomStringConvertible where K: PreferenceKey { |
228 | | - @OptionalAttribute |
229 | | - var info: DynamicContainer.Info? |
| 228 | + @OptionalAttribute var info: DynamicContainer.Info? |
| 229 | + |
| 230 | + init() { |
| 231 | + _openSwiftUIEmptyStub() |
| 232 | + } |
230 | 233 |
|
231 | 234 | var value: K.Value { |
232 | | - // TODO: |
233 | | - _openSwiftUIUnimplementedWarning() |
234 | | - return K.defaultValue |
| 235 | + let info = info! |
| 236 | + let inusedCount = info.items.count - info.unusedCount |
| 237 | + let validCount = inusedCount - info.removedCount |
| 238 | + |
| 239 | + var value = K.defaultValue |
| 240 | + let includesRemovedValues = inusedCount != validCount && K._includesRemovedValues |
| 241 | + let count = includesRemovedValues ? inusedCount : validCount |
| 242 | + |
| 243 | + var initialValue = true |
| 244 | + for index in 0 ..< count { |
| 245 | + let itemIndex: Int |
| 246 | + if let displayMap = info.displayMap { |
| 247 | + if includesRemovedValues { |
| 248 | + itemIndex = Int(displayMap[validCount + index]) |
| 249 | + } else { |
| 250 | + itemIndex = Int(displayMap[index]) |
| 251 | + } |
| 252 | + } else { |
| 253 | + if includesRemovedValues { |
| 254 | + itemIndex = index >= info.removedCount ? index &- info.removedCount : validCount &+ index |
| 255 | + } else { |
| 256 | + itemIndex = index |
| 257 | + } |
| 258 | + } |
| 259 | + let item = info.items[itemIndex] |
| 260 | + guard let attribute = item.outputs[K.self] else { |
| 261 | + return value |
| 262 | + } |
| 263 | + if initialValue { |
| 264 | + value = attribute.value |
| 265 | + } else { |
| 266 | + K.reduce(value: &value) { |
| 267 | + attribute.value |
| 268 | + } |
| 269 | + } |
| 270 | + initialValue = false |
| 271 | + } |
| 272 | + return value |
235 | 273 | } |
236 | 274 |
|
237 | 275 | var description: String { |
238 | 276 | "∪+ \(K.readableName)" |
239 | 277 | } |
| 278 | + |
| 279 | + static var initialValue: K.Value { K.defaultValue } |
240 | 280 | } |
241 | 281 |
|
242 | 282 | // MARK: - DynamicContainerInfo |
|
0 commit comments