Skip to content

Commit 3ddfbd7

Browse files
committed
Update ViewAlias
1 parent 6561d64 commit 3ddfbd7

File tree

2 files changed

+253
-43
lines changed

2 files changed

+253
-43
lines changed
Lines changed: 253 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,253 @@
1+
//
2+
// ViewAlias.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
// ID: D9F7AF928092578A4B8FA861B49E2161 (SwiftUI)
8+
9+
import OpenGraphShims
10+
@_spi(ForOpenSwiftUIOnly) import OpenSwiftUICore
11+
12+
// MARK: - ViewAlias
13+
14+
protocol ViewAlias: PrimitiveView {
15+
init()
16+
}
17+
18+
// MARK: - View + ViewAlias Extension
19+
20+
extension View {
21+
func viewAlias<Alias, Source>(
22+
_ alias: Alias.Type,
23+
_ source: () -> Source
24+
) -> some View where Alias: ViewAlias, Source: View {
25+
modifier(StaticSourceWriter<Alias, Source>(source: source()))
26+
}
27+
28+
func viewAlias<Predicate, Alias, Source>(
29+
if predicate: Predicate.Type,
30+
_ alias: Alias.Type,
31+
_ source: () -> Source
32+
) -> some View where Predicate: ViewInputPredicate, Alias: ViewAlias, Source: View {
33+
modifier(StaticSourceWriter<Alias, Source>(source: source()).requiring(predicate))
34+
}
35+
36+
func optionalViewAlias<Alias, Source>(
37+
_ alias: Alias.Type,
38+
_ source: () -> Source?
39+
) -> some View where Alias: ViewAlias, Source: View {
40+
modifier(OptionalSourceWriter<Alias, Source>(source: source()))
41+
}
42+
}
43+
44+
// MARK: - AnySourceFormula
45+
46+
private protocol AnySourceFormula {
47+
static func makeView<Alias>(
48+
view: _GraphValue<Alias>,
49+
source: AnySource,
50+
inputs: _ViewInputs
51+
) -> _ViewOutputs where Alias: ViewAlias
52+
53+
static func makeViewList<Alias>(
54+
view: _GraphValue<Alias>,
55+
source: AnySource,
56+
inputs: _ViewListInputs
57+
) -> _ViewListOutputs where Alias: ViewAlias
58+
59+
static func viewListCount(
60+
source: AnySource,
61+
inputs: _ViewListCountInputs
62+
) -> Int?
63+
}
64+
65+
// MARK: - OptionalViewAlias
66+
67+
struct OptionalViewAlias<Alias>: DynamicProperty where Alias: ViewAlias {
68+
static func _makeProperty<Value>(in buffer: inout _DynamicPropertyBuffer, container: _GraphValue<Value>, fieldOffset: Int, inputs: inout _GraphInputs) {
69+
if let source = inputs[SourceInput<Alias>.self].top {
70+
if let valueIsNil = source.valueIsNil {
71+
let box = OptionalSourceBox(sourceIsNil: valueIsNil)
72+
buffer.append(box, fieldOffset: fieldOffset)
73+
} else {
74+
let box = StaticSourceBox(sourceExists: true)
75+
buffer.append(box, fieldOffset: fieldOffset)
76+
}
77+
} else {
78+
let box = StaticSourceBox(sourceExists: false)
79+
buffer.append(box, fieldOffset: fieldOffset)
80+
}
81+
}
82+
83+
var sourceExists: Bool
84+
85+
var wrappedValue: Alias? {
86+
sourceExists ? Alias() : nil
87+
}
88+
89+
private struct OptionalSourceBox: DynamicPropertyBox {
90+
@Attribute var sourceIsNil: Bool
91+
92+
func update(property: inout OptionalViewAlias, phase: ViewPhase) -> Bool {
93+
let (sourceIsNil, changed) = $sourceIsNil.changedValue()
94+
property.sourceExists = !sourceIsNil
95+
return changed
96+
}
97+
}
98+
99+
private struct StaticSourceBox: DynamicPropertyBox {
100+
var sourceExists: Bool
101+
102+
func update(property: inout OptionalViewAlias, phase: ViewPhase) -> Bool {
103+
property.sourceExists = sourceExists
104+
return false
105+
}
106+
}
107+
}
108+
109+
// MARK: - OptionalSourceWriter
110+
111+
private struct OptionalSourceWriter<Alias, Source>: PrimitiveViewModifier, _GraphInputsModifier where Alias: ViewAlias, Source: View {
112+
var source: Source?
113+
114+
static func _makeInputs(modifier: _GraphValue<Self>, inputs: inout _GraphInputs) {
115+
inputs.append(
116+
AnySource(modifier.value[offset: { .of(&$0.source) }]),
117+
to: SourceInput<Alias>.self
118+
)
119+
}
120+
}
121+
122+
// MARK: - StaticSourceWriter
123+
124+
private struct StaticSourceWriter<Alias, Source>: PrimitiveViewModifier, _GraphInputsModifier where Alias: ViewAlias, Source: View {
125+
var source: Source
126+
127+
static func _makeInputs(modifier: _GraphValue<Self>, inputs: inout _GraphInputs) {
128+
inputs.append(
129+
AnySource(modifier.value[offset: { .of(&$0.source) }]),
130+
to: SourceInput<Alias>.self
131+
)
132+
}
133+
}
134+
135+
// MARK: - SourceFormula
136+
137+
private struct SourceFormula<Source>: AnySourceFormula where Source: View {
138+
static func makeView<Alias>(
139+
view: _GraphValue<Alias>,
140+
source: AnySource,
141+
inputs: _ViewInputs
142+
) -> _ViewOutputs where Alias: ViewAlias {
143+
guard let attribute = source.value.attribute else {
144+
return .init()
145+
}
146+
return if source.valueIsNil == nil {
147+
Optional<Source>.makeDebuggableView(
148+
view: _GraphValue(Attribute(identifier: attribute)),
149+
inputs: inputs
150+
)
151+
} else {
152+
Source.makeDebuggableView(
153+
view: _GraphValue(Attribute(identifier: attribute)),
154+
inputs: inputs
155+
)
156+
}
157+
}
158+
159+
static func makeViewList<Alias>(
160+
view: _GraphValue<Alias>,
161+
source: AnySource,
162+
inputs: _ViewListInputs
163+
) -> _ViewListOutputs where Alias: ViewAlias {
164+
guard let attribute = source.value.attribute else {
165+
return .emptyViewList(inputs: inputs)
166+
}
167+
return if source.valueIsNil == nil {
168+
Optional<Source>.makeDebuggableViewList(
169+
view: _GraphValue(Attribute(identifier: attribute)),
170+
inputs: inputs
171+
)
172+
} else {
173+
Source.makeDebuggableViewList(
174+
view: _GraphValue(Attribute(identifier: attribute)),
175+
inputs: inputs
176+
)
177+
}
178+
}
179+
180+
static func viewListCount(
181+
source: AnySource,
182+
inputs: _ViewListCountInputs
183+
) -> Int? {
184+
if source.valueIsNil == nil {
185+
Optional<Source>._viewListCount(inputs: inputs)
186+
} else {
187+
Source._viewListCount(inputs: inputs)
188+
}
189+
}
190+
}
191+
192+
// MARK: - AnySource
193+
194+
private struct AnySource: GraphReusable {
195+
let formula: AnySourceFormula.Type
196+
var value: AnyWeakAttribute
197+
let valueIsNil: Attribute<Bool>?
198+
199+
init<V>(_ view: Attribute<V>) where V: View {
200+
formula = SourceFormula<V>.self
201+
value = AnyWeakAttribute(view.identifier)
202+
valueIsNil = nil
203+
}
204+
205+
init<V>(_ view: Attribute<V?>) where V: View {
206+
formula = SourceFormula<V?>.self
207+
value = AnyWeakAttribute(view.identifier)
208+
valueIsNil = Attribute(isNil(input: view))
209+
}
210+
211+
struct isNil<Input>: Rule, AsyncAttribute {
212+
@Attribute
213+
var input: Input?
214+
215+
var value: Bool { input == nil }
216+
}
217+
218+
mutating func makeReusable(indirectMap: IndirectAttributeMap) {
219+
guard let attribute = value.attribute else {
220+
return
221+
}
222+
if let result = indirectMap.map[attribute] {
223+
value = AnyWeakAttribute(result)
224+
} else {
225+
let indirect = indirectMap.subgraph.apply {
226+
attribute.createIndirect()
227+
}
228+
indirectMap.map[attribute] = indirect
229+
value = AnyWeakAttribute(indirect)
230+
}
231+
}
232+
233+
func tryToReuse(by other: AnySource, indirectMap: IndirectAttributeMap, testOnly: Bool) -> Bool {
234+
guard formula == other.formula,
235+
let attribute = value.attribute,
236+
let result = indirectMap.map[attribute],
237+
let otherAttribute = other.value.attribute
238+
else {
239+
ReuseTrace.traceNeverMadeReusableFailure(AnySource.self)
240+
return false
241+
}
242+
if !testOnly {
243+
result.source = otherAttribute
244+
}
245+
return true
246+
}
247+
}
248+
249+
// MARK: - SourceInput
250+
251+
private struct SourceInput<Alias>: ViewInput where Alias: ViewAlias {
252+
static var defaultValue: Stack<AnySource> { Stack() }
253+
}

Sources/OpenSwiftUICore/View/ViewAlias.swift

Lines changed: 0 additions & 43 deletions
This file was deleted.

0 commit comments

Comments
 (0)