Skip to content

Commit 7aeac27

Browse files
committed
Update AlignmentID
1 parent 19ced57 commit 7aeac27

File tree

3 files changed

+82
-55
lines changed

3 files changed

+82
-55
lines changed

Sources/OpenSwiftUICore/Layout/Alignment/AlignmentID.swift renamed to Sources/OpenSwiftUICore/Layout/Alignment/AlignmentGuide.swift

Lines changed: 62 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,15 @@
11
//
2-
// AlignmentID.swift
3-
// OpenSwiftUI
2+
// AlignmentGuide.swift
3+
// OpenSwiftUICore
44
//
5-
// Audited for iOS 15.5
65
// Status: Complete
6+
// ID: E20796D15DD3D417699102559E024115 (SwiftUI)
7+
// ID: 1135C055CD2C2B1265C25B13E3E74C01 (SwiftUICore)
78

89
public import Foundation
910

11+
// MARK: - AlignmentID [6.4.41]
12+
1013
/// A type that you use to create custom alignment guides.
1114
///
1215
/// Every built-in alignment guide that ``VerticalAlignment`` or
@@ -70,7 +73,7 @@ public import Foundation
7073
/// of the top-most rectangle in each stack are aligned with each
7174
/// other.](AlignmentId-1-iOS)
7275
///
73-
/// You can also use the ``View/alignmentGuide(_:computeValue:)-6y3u2`` view
76+
/// You can also use the ``View/alignmentGuide(_:computeValue:)`` view
7477
/// modifier to alter the behavior of your custom guide for a view, as you
7578
/// might alter a built-in guide. For example, you can change
7679
/// one of the stacks of stripes from the previous example to align its
@@ -119,7 +122,7 @@ public protocol AlignmentID {
119122
///
120123
/// You can override the default value that this method returns for a
121124
/// particular guide by adding the
122-
/// ``View/alignmentGuide(_:computeValue:)-9mdoh`` view modifier to a
125+
/// ``View/alignmentGuide(_:computeValue:)`` view modifier to a
123126
/// particular view.
124127
///
125128
/// - Parameter context: The context of the view that you apply
@@ -132,7 +135,9 @@ public protocol AlignmentID {
132135
/// - Returns: The offset of the guide from the origin in the
133136
/// view's coordinate space.
134137
static func defaultValue(in context: ViewDimensions) -> CGFloat
135-
138+
139+
/// Updates `parentValue` with the `n`th explicit child guide value, as
140+
/// projected into the parent's coordinate space.
136141
static func _combineExplicit(childValue: CGFloat, _ n: Int, into parentValue: inout CGFloat?)
137142
}
138143

@@ -151,10 +156,61 @@ extension AlignmentID {
151156
let n = CGFloat(n)
152157
parentValue = (value * n + childValue) / (n + 1.0)
153158
}
159+
160+
package static func combineExplicit<S>(_ values: S) -> CGFloat? where S: Sequence, S.Element == CGFloat? {
161+
var result: CGFloat? = nil
162+
var n = 0
163+
for childValue in values {
164+
guard let childValue else {
165+
continue
166+
}
167+
_combineExplicit(childValue: childValue, n, into: &result)
168+
n += 1
169+
}
170+
return result
171+
}
154172
}
155173

156174
protocol FrameAlignment: AlignmentID {}
157175

158176
extension FrameAlignment {
159177
static func _combineExplicit(childValue _: CGFloat, _: Int, into _: inout CGFloat?) {}
160178
}
179+
180+
181+
// MARK: - AlignmentKey [6.4.41]
182+
183+
@usableFromInline
184+
@frozen
185+
package struct AlignmentKey: Hashable, Comparable {
186+
private let bits: UInt
187+
188+
@usableFromInline
189+
package static func < (lhs: AlignmentKey, rhs: AlignmentKey) -> Bool {
190+
lhs.bits < rhs.bits
191+
}
192+
193+
@AtomicBox
194+
private static var typeCache = TypeCache(typeIDs: [:], types: [])
195+
196+
struct TypeCache {
197+
var typeIDs: [ObjectIdentifier: UInt]
198+
var types: [AlignmentID.Type]
199+
}
200+
201+
init(id: AlignmentID.Type, axis _: Axis) {
202+
let index: UInt
203+
if let value = AlignmentKey.typeCache.typeIDs[ObjectIdentifier(id)] {
204+
index = value
205+
} else {
206+
index = UInt(AlignmentKey.typeCache.types.count)
207+
AlignmentKey.typeCache.types.append(id)
208+
AlignmentKey.typeCache.typeIDs[ObjectIdentifier(id)] = index
209+
}
210+
bits = index * 2 + 3
211+
}
212+
213+
var id: AlignmentID.Type {
214+
AlignmentKey.typeCache.types[Int(bits / 2 - 1)]
215+
}
216+
}

Sources/OpenSwiftUICore/Layout/Alignment/AlignmentKey.swift

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

Tests/OpenSwiftUICoreTests/Layout/Alignment/AlignmentIDTests.swift renamed to Tests/OpenSwiftUICoreTests/Layout/Alignment/AlignmentGuideTests.swift

Lines changed: 20 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,13 @@
11
//
2-
// AlignmentIDTests.swift
2+
// AlignmentGuideTests.swift
33
// OpenSwiftUICoreTests
44

5-
@testable import OpenSwiftUICore
6-
import Testing
75
import Foundation
6+
import Numerics
7+
import OpenSwiftUICore
8+
import Testing
9+
10+
// MARK: - AlignmentIDTests
811

912
struct AlignmentIDTests {
1013
private struct TestAlignment: AlignmentID {
@@ -21,9 +24,7 @@ struct AlignmentIDTests {
2124
into: &value
2225
)
2326
let value = try #require(value)
24-
// TODO: use swift-numerics
25-
// https://github.com/apple/swift-testing/issues/165
26-
#expect(abs(value - CGFloat(n) / 2) <= 0.0001)
27+
#expect(value.isApproximatelyEqual(to: CGFloat(n) / 2))
2728
}
2829
}
2930

@@ -38,7 +39,19 @@ struct AlignmentIDTests {
3839
into: &value
3940
)
4041
let value = try #require(value)
41-
#expect(abs(value - child) <= 0.0001)
42+
#expect(value.isApproximatelyEqual(to: child))
4243
}
4344
}
45+
46+
@Test
47+
func combineSequence() throws {
48+
var values: [CGFloat?] = [1, 3, 5]
49+
let result = TestAlignment.combineExplicit(values) ?? .zero
50+
#expect(result.isApproximatelyEqual(to: 3.0))
51+
52+
values.append(nil)
53+
values.append(nil)
54+
let result2 = TestAlignment.combineExplicit(values) ?? .zero
55+
#expect(result2.isApproximatelyEqual(to: 3.0))
56+
}
4457
}

0 commit comments

Comments
 (0)