Skip to content

Commit 75db3fa

Browse files
authored
Update DynamicPropertyCache (#28)
* Update _GraphInputs * remove mode parameter pass * Update DynamicPropertyCache * Update enum and optional’s fields implementation * Update CacheTests * Update FieldsLayout implementation * Update DynamicPropertyCache implementation * Remove internal structure * Update DynamicProperty * Update _DynamicPropertyBuffer * Update OpenGraph dependency version * Fix compiler warning
1 parent 366262f commit 75db3fa

File tree

13 files changed

+353
-97
lines changed

13 files changed

+353
-97
lines changed

Package.resolved

+1-1
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@
1515
"location" : "https://github.com/OpenSwiftUIProject/OpenGraph",
1616
"state" : {
1717
"branch" : "main",
18-
"revision" : "17b4ef3ead4c0c1bce51c965d6a1169f4e65c61d"
18+
"revision" : "ca3f8991a8a9564d581a08d9ce43b216c9afe01b"
1919
}
2020
},
2121
{
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
struct CachedEnvironment {}

Sources/OpenSwiftUI/DataAndStorage/Internal/Property/PropertyList.swift

+2-3
Original file line numberDiff line numberDiff line change
@@ -63,8 +63,7 @@ struct PropertyList: CustomStringConvertible {
6363
if let result = find(elements.map { .passUnretained($0) }, key: keyType) {
6464
guard !compareValues(
6565
newValue,
66-
result.takeUnretainedValue().value,
67-
mode: ._3
66+
result.takeUnretainedValue().value
6867
) else {
6968
return
7069
}
@@ -270,7 +269,7 @@ private class TypedElement<Key: PropertyKey>: PropertyList.Element {
270269
guard !ignoredTypes.contains(ObjectIdentifier(Key.self)) else {
271270
return true
272271
}
273-
guard compareValues(value, typedElement.value, mode: ._3) else {
272+
guard compareValues(value, typedElement.value) else {
274273
return false
275274
}
276275
ignoredTypes.insert(ObjectIdentifier(Key.self))

Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/DynamicProperty.swift

+11-25
Original file line numberDiff line numberDiff line change
@@ -4,16 +4,23 @@
44
//
55
// Created by Kyle on 2023/11/2.
66
// Lastest Version: iOS 15.5
7-
// Status: WIP
7+
// Status: Complete
88

99
/// An interface for a stored variable that updates an external property of a
1010
/// view.
1111
///
1212
/// The view gives values to these properties prior to recomputing the view's
1313
/// ``View/body-swift.property``.
1414
public protocol DynamicProperty {
15-
static func _makeProperty<V>(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue<V>, fieldOffset: Int, inputs: inout _GraphInputs)
15+
static func _makeProperty<Value>(
16+
in buffer: inout _DynamicPropertyBuffer,
17+
container: _GraphValue<Value>,
18+
fieldOffset: Int,
19+
inputs: inout _GraphInputs
20+
)
21+
1622
static var _propertyBehaviors: UInt32 { get }
23+
1724
/// Updates the underlying value of the stored value.
1825
///
1926
/// OpenSwiftUI calls this function before rendering a view's
@@ -23,28 +30,7 @@ public protocol DynamicProperty {
2330
}
2431

2532
extension DynamicProperty {
26-
public static func _makeProperty<V>(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue<V>, fieldOffset: Int, inputs: inout _GraphInputs) {
27-
makeEmbeddedProperties(in: &buffer, container: container, fieldOffset: fieldOffset, inputs: &inputs)
28-
// TODO
29-
buffer.append(EmbeddedDynamicPropertyBox<Self>(), fieldOffset: fieldOffset)
30-
}
31-
32-
static func makeEmbeddedProperties<V>(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue<V>, fieldOffset: Int, inputs: inout _GraphInputs) -> () {
33-
let fields = DynamicPropertyCache.fields(of: self)
34-
// TODO
35-
buffer.addFields(fields, container: container, inputs: &inputs, baseOffset: fieldOffset)
36-
}
37-
38-
public mutating func update() {}
3933
public static var _propertyBehaviors: UInt32 { 0 }
40-
}
41-
42-
private struct EmbeddedDynamicPropertyBox<Value: DynamicProperty>: DynamicPropertyBox {
43-
typealias Property = Value
44-
func destroy() {}
45-
func reset() {}
46-
func update(property: inout Value, phase _: _GraphInputs.Phase) -> Bool {
47-
property.update()
48-
return false
49-
}
34+
35+
public mutating func update() {}
5036
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
//
2+
// DynamicPropertyBehaviors.swift
3+
// OpenSwiftUI
4+
//
5+
// Created by Kyle on 2024/1/6.
6+
// Lastest Version: iOS 15.5
7+
// Status: Complete
8+
9+
struct DynamicPropertyBehaviors: OptionSet {
10+
let rawValue: UInt32
11+
}
+3-3
Original file line numberDiff line numberDiff line change
@@ -11,9 +11,9 @@ protocol DynamicPropertyBox<Property>: DynamicProperty {
1111
func destroy()
1212
func reset()
1313
func update(property: inout Property, phase: _GraphInputs.Phase) -> Bool
14-
func getState<S>(type: S.Type) -> Binding<S>?
14+
func getState<Value>(type: Value.Type) -> Binding<Value>?
1515
}
1616

17-
extension DynamicProperty {
18-
func getState<S>(type: S.Type) -> Binding<S>? { nil }
17+
extension DynamicPropertyBox {
18+
func getState<Value>(type _: Value.Type) -> Binding<Value>? { nil }
1919
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,163 @@
1+
//
2+
// DynamicPropertyCache.swift
3+
// OpenSwiftUI
4+
//
5+
// Created by Kyle on 2024/1/10.
6+
// Lastest Version: iOS 15.5
7+
// Status: Complete
8+
// ID: 49D2A32E637CD497C6DE29B8E060A506
9+
10+
internal import OpenGraphShims
11+
12+
// MARK: - DynamicPropertyCache
13+
14+
struct DynamicPropertyCache {
15+
private static var cache = MutableBox([ObjectIdentifier: Fields]())
16+
17+
static func fields(of type: Any.Type) -> Fields {
18+
if let fields = cache.value[ObjectIdentifier(type)] {
19+
return fields
20+
}
21+
let fields: Fields
22+
let typeID = OGTypeID(type)
23+
switch typeID.kind {
24+
case .enum, .optional:
25+
var taggedFields: [TaggedFields] = []
26+
_ = typeID.forEachField(options: [._2, ._4]) { name, offset, fieldType in
27+
var fields: [Field] = []
28+
let tupleType = OGTupleType(fieldType)
29+
for index in tupleType.indices {
30+
guard let dynamicPropertyType = tupleType.type(at: index) as? DynamicProperty.Type else {
31+
break
32+
}
33+
let offset = tupleType.offset(at: index)
34+
let field = Field(type: dynamicPropertyType, offset: offset, name: name)
35+
fields.append(field)
36+
}
37+
if !fields.isEmpty {
38+
let taggedField = TaggedFields(tag: offset, fields: fields)
39+
taggedFields.append(taggedField)
40+
}
41+
return true
42+
}
43+
fields = Fields(layout: .sum(type, taggedFields))
44+
case .struct, .tuple:
45+
var fieldArray: [Field] = []
46+
_ = typeID.forEachField(options: [._2]) { name, offset, fieldType in
47+
guard let dynamicPropertyType = fieldType as? DynamicProperty.Type else {
48+
return true
49+
}
50+
let field = Field(type: dynamicPropertyType, offset: offset, name: name)
51+
fieldArray.append(field)
52+
return true
53+
}
54+
fields = Fields(layout: .product(fieldArray))
55+
default:
56+
fields = Fields(layout: .product([]))
57+
break
58+
}
59+
if fields.behaviors.contains(.init(rawValue: 3)) {
60+
Log.runtimeIssues("%s is marked async, but contains properties that require the main thread.", [_typeName(type)])
61+
}
62+
cache.value[ObjectIdentifier(type)] = fields
63+
return fields
64+
}
65+
}
66+
67+
// MARK: - DynamicPropertyCache.Fields
68+
69+
extension DynamicPropertyCache {
70+
struct Fields {
71+
var layout: Layout
72+
var behaviors: DynamicPropertyBehaviors
73+
74+
enum Layout {
75+
case product([Field])
76+
case sum(Any.Type, [TaggedFields])
77+
}
78+
79+
init(layout: Layout) {
80+
var behaviors: UInt32 = 0
81+
switch layout {
82+
case let .product(fields):
83+
for field in fields {
84+
behaviors |= field.type._propertyBehaviors
85+
}
86+
case let .sum(_, taggedFields):
87+
for taggedField in taggedFields {
88+
for field in taggedField.fields {
89+
behaviors |= field.type._propertyBehaviors
90+
}
91+
}
92+
}
93+
self.layout = layout
94+
self.behaviors = .init(rawValue: behaviors)
95+
}
96+
}
97+
}
98+
99+
// MARK: - DynamicPropertyCache.Field
100+
101+
extension DynamicPropertyCache {
102+
struct Field {
103+
var type: DynamicProperty.Type
104+
var offset: Int
105+
var name: UnsafePointer<Int8>?
106+
}
107+
}
108+
109+
// MARK: - DynamicPropertyCache.TaggedFields
110+
111+
extension DynamicPropertyCache {
112+
struct TaggedFields {
113+
var tag: Int
114+
var fields: [Field]
115+
}
116+
}
117+
118+
// MARK: - EmbeddedDynamicPropertyBox
119+
120+
private struct EmbeddedDynamicPropertyBox<Value: DynamicProperty>: DynamicPropertyBox {
121+
typealias Property = Value
122+
func destroy() {}
123+
func reset() {}
124+
func update(property: inout Property, phase _: _GraphInputs.Phase) -> Bool {
125+
property.update()
126+
return false
127+
}
128+
}
129+
130+
extension DynamicProperty {
131+
public static func _makeProperty<Value>(
132+
in buffer: inout _DynamicPropertyBuffer,
133+
container: _GraphValue<Value>,
134+
fieldOffset: Int,
135+
inputs: inout _GraphInputs
136+
) {
137+
makeEmbeddedProperties(
138+
in: &buffer,
139+
container: container,
140+
fieldOffset: fieldOffset,
141+
inputs: &inputs
142+
)
143+
buffer.append(
144+
EmbeddedDynamicPropertyBox<Self>(),
145+
fieldOffset: fieldOffset
146+
)
147+
}
148+
149+
static func makeEmbeddedProperties<Value>(
150+
in buffer: inout _DynamicPropertyBuffer,
151+
container: _GraphValue<Value>,
152+
fieldOffset: Int,
153+
inputs: inout _GraphInputs
154+
) -> () {
155+
let fields = DynamicPropertyCache.fields(of: self)
156+
buffer.addFields(
157+
fields,
158+
container: container,
159+
inputs: &inputs,
160+
baseOffset: fieldOffset
161+
)
162+
}
163+
}

Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/Internal/TODO/DynamicPropertyCache.swift

-38
This file was deleted.

Sources/OpenSwiftUI/DataAndStorage/ModelData/DynamicProperty/TODO/_DynamicPropertyBuffer.swift

-20
This file was deleted.

0 commit comments

Comments
 (0)