Skip to content

Commit a7592b6

Browse files
authored
Improve dynamic "case" lookup performance (pointfreeco#137)
When writing algorithms against dynamic "case" lookup it's more performant to work directly with the case-pathable type rather than use case key paths, which resolve lazily and have a higher cost.
1 parent 8059322 commit a7592b6

File tree

4 files changed

+153
-139
lines changed

4 files changed

+153
-139
lines changed

Examples/CaseStudies/08-Routing.swift

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,10 @@ private let readMe = """
55
This case study demonstrates how to power multiple forms of navigation from a single destination \
66
enum that describes all of the possible destinations one can travel to from this screen.
77
8-
The screen has four navigation destinations: an alert, a confirmation dialog, a navigation link to a count stepper, \
9-
and a modal sheet to a count stepper. The state for each of these destinations is held as \
10-
associated data of an enum, and bindings to the cases of that enum are derived using the tools \
11-
in this library.
8+
The screen has four navigation destinations: an alert, a confirmation dialog, a navigation link \
9+
to a count stepper, and a modal sheet to a count stepper. The state for each of these \
10+
destinations is held as associated data of an enum, and bindings to the cases of that enum are \
11+
derived using the tools in this library.
1212
"""
1313

1414
@CasePathable

Package.resolved

Lines changed: 13 additions & 4 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Sources/SwiftUINavigation/Binding.swift

Lines changed: 15 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -11,15 +11,16 @@
1111
/// - Parameter keyPath: A case key path to a specific associated value.
1212
/// - Returns: A new binding.
1313
public subscript<Member>(
14-
dynamicMember keyPath: CaseKeyPath<Value, Member>
14+
dynamicMember keyPath: KeyPath<Value.AllCasePaths, AnyCasePath<Value, Member>>
1515
) -> Binding<Member>?
1616
where Value: CasePathable {
17-
Binding<Member>(
17+
let casePath = Value.allCasePaths[keyPath: keyPath]
18+
return Binding<Member>(
1819
unwrapping: Binding<Member?>(
19-
get: { self.wrappedValue[case: keyPath] },
20+
get: { casePath.extract(from: self.wrappedValue) },
2021
set: { newValue, transaction in
2122
guard let newValue else { return }
22-
self.transaction(transaction).wrappedValue[case: keyPath] = newValue
23+
self.transaction(transaction).wrappedValue = casePath.embed(newValue)
2324
}
2425
)
2526
)
@@ -31,20 +32,22 @@
3132
///
3233
/// - Parameter keyPath: A case key path to a specific associated value.
3334
/// - Returns: A new binding.
34-
public subscript<Enum, AssociatedValue>(
35-
dynamicMember keyPath: CaseKeyPath<Enum, AssociatedValue>
36-
) -> Binding<AssociatedValue?>
35+
public subscript<Enum: CasePathable, Member>(
36+
dynamicMember keyPath: KeyPath<Enum.AllCasePaths, AnyCasePath<Enum, Member>>
37+
) -> Binding<Member?>
3738
where Value == Enum? {
38-
return Binding<AssociatedValue?>(
39-
get: { self.wrappedValue[case: (\Enum?.Cases.some).appending(path: keyPath)] },
39+
let casePath = Enum.allCasePaths[keyPath: keyPath]
40+
return Binding<Member?>(
41+
get: {
42+
guard let wrappedValue = self.wrappedValue else { return nil }
43+
return casePath.extract(from: wrappedValue)
44+
},
4045
set: { newValue, transaction in
4146
guard let newValue else {
4247
self.transaction(transaction).wrappedValue = nil
4348
return
4449
}
45-
self.transaction(transaction).wrappedValue[
46-
case: (\Enum?.Cases.some).appending(path: keyPath)
47-
] = newValue
50+
self.transaction(transaction).wrappedValue = casePath.embed(newValue)
4851
}
4952
)
5053
}

SwiftUINavigation.xcworkspace/xcshareddata/swiftpm/Package.resolved

Lines changed: 121 additions & 119 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

0 commit comments

Comments
 (0)