Skip to content

Commit 64fe029

Browse files
authored
Add IdentifiedView (#182)
* Update folder structure of Hosting stuff * Update IdentifiedViewProxy * Update TestIDView * Add IdentifiedViewTree * Update test case
2 parents f1ba63a + b8b424c commit 64fe029

File tree

18 files changed

+320
-53
lines changed

18 files changed

+320
-53
lines changed

Sources/OpenSwiftUI/Integration/UIKit/AnyUIHostingView.swift renamed to Sources/OpenSwiftUI/Integration/Hosting/UIKit/AnyUIHostingView.swift

File renamed without changes.

Sources/OpenSwiftUI/Integration/UIKit/UIGraphicsView.swift renamed to Sources/OpenSwiftUI/Integration/Hosting/UIKit/UIGraphicsView.swift

File renamed without changes.

Sources/OpenSwiftUI/Integration/UIKit/UIHostingController.swift renamed to Sources/OpenSwiftUI/Integration/Hosting/UIKit/UIHostingController.swift

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -47,10 +47,15 @@ open class UIHostingController<Content> : UIViewController where Content : View
4747
get { host.rootView }
4848
_modify { yield &host.rootView }
4949
}
50+
51+
public func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void) {
52+
host._forEachIdentifiedView(body: body)
53+
}
5054
}
5155

5256
@available(macOS, unavailable)
5357
extension UIHostingController: _UIHostingViewable where Content == AnyView {
58+
5459
}
5560

5661
@available(macOS, unavailable)

Sources/OpenSwiftUI/Integration/UIKit/UIHostingView.swift renamed to Sources/OpenSwiftUI/Integration/Hosting/UIKit/UIHostingView.swift

Lines changed: 16 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -7,7 +7,9 @@
77
// ID: FAF0B683EB49BE9BABC9009857940A1E
88

99
#if os(iOS)
10-
@_spi(ForOpenSwiftUIOnly) public import OpenSwiftUICore
10+
@_spi(ForOpenSwiftUIOnly)
11+
@_spi(Private)
12+
public import OpenSwiftUICore
1113
public import UIKit
1214

1315
@available(macOS, unavailable)
@@ -151,6 +153,19 @@ open class _UIHostingView<Content>: UIView where Content: View {
151153
// TODO
152154
func clearUpdateTimer() {
153155
}
156+
157+
func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void) {
158+
let tree = preferenceValue(_IdentifiedViewsKey.self)
159+
let adjustment = { [weak self](rect: inout CGRect) in
160+
guard let self else { return }
161+
rect = convert(rect, from: nil)
162+
}
163+
tree.forEach { proxy in
164+
var proxy = proxy
165+
proxy.adjustment = adjustment
166+
body(proxy)
167+
}
168+
}
154169
}
155170

156171
extension _UIHostingView: ViewRendererHost {

Sources/OpenSwiftUI/Integration/UIKit/UIHostingViewable.swift renamed to Sources/OpenSwiftUI/Integration/Hosting/UIKit/UIHostingViewable.swift

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -13,7 +13,7 @@ import Foundation
1313
public protocol _UIHostingViewable: AnyObject {
1414
// var rootView: AnyView { get set }
1515
// func _render(seconds: Double)
16-
// func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void)
16+
func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void)
1717
// func sizeThatFits(in size: CGSize) -> CGSize
1818
// var _disableSafeArea: Bool { get set }
1919
//// var _rendererConfiguration: _RendererConfiguration { get set }

Sources/OpenSwiftUI/Test/TestApp.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6,6 +6,9 @@
66
// Status: WIP
77
// ID: A519B5B95CA8FF4E3445832668F0B2D2
88

9+
@_spi(Testing)
10+
import OpenSwiftUICore
11+
912
public struct _TestApp {
1013
public init() {
1114
preconditionFailure("TODO")

Sources/OpenSwiftUI/Test/TestIDView.swift

Lines changed: 0 additions & 39 deletions
This file was deleted.
Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,28 @@
1+
//
2+
// IdentifiedViewTree.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
public enum _IdentifiedViewTree {
9+
case empty
10+
case proxy(_IdentifiedViewProxy)
11+
case array([_IdentifiedViewTree])
12+
13+
public func forEach(_ body: (_IdentifiedViewProxy) -> Void) {
14+
switch self {
15+
case .empty:
16+
break
17+
case let .proxy(proxy):
18+
body(proxy)
19+
case let .array(array):
20+
for treeElement in array {
21+
treeElement.forEach(body)
22+
}
23+
}
24+
}
25+
}
26+
27+
@available(*, unavailable)
28+
extension _IdentifiedViewTree: Sendable {}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// IdentifiedViewsKey.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
@_spi(Private)
9+
public import OpenSwiftUICore
10+
11+
public struct _IdentifiedViewsKey {
12+
public typealias Value = _IdentifiedViewTree
13+
14+
public static let defaultValue: _IdentifiedViewTree = .empty
15+
16+
public static func reduce(value: inout _IdentifiedViewTree, nextValue: () -> _IdentifiedViewTree) {
17+
let newValue = nextValue()
18+
switch (value, newValue) {
19+
case (_, .empty):
20+
break
21+
case (.empty, _):
22+
value = newValue
23+
case let (.proxy(oldProxy), .proxy(newProxy)):
24+
value = .array([.proxy(oldProxy)] + [.proxy(newProxy)])
25+
case let (.array(oldArray), .proxy(newProxy)):
26+
value = .array(oldArray + [.proxy(newProxy)])
27+
case let (.proxy(oldProxy), .array(newArray)):
28+
value = .array([.proxy(oldProxy)] + newArray)
29+
case let (.array(oldArray), .array(newArray)):
30+
value = .array(oldArray + newArray)
31+
}
32+
}
33+
}
34+
35+
@available(*, unavailable)
36+
extension _IdentifiedViewsKey: Sendable {}
37+
38+
@_spi(Private)
39+
extension _IdentifiedViewsKey: HostPreferenceKey {}

Sources/OpenSwiftUICore/Data/Preference/PreferenceKey.swift

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -36,12 +36,19 @@ public protocol PreferenceKey {
3636
/// - nextValue: A closure that returns the next value in the sequence.
3737
static func reduce(value: inout Value, nextValue: () -> Value)
3838

39+
/// If true `reduce()` will also see preference values for views
40+
/// that have active removal transitions. The default
41+
/// implementation returns false.
3942
static var _includesRemovedValues: Bool { get }
4043

44+
/// If true the preference may be read via the renderer host API.
45+
/// Defaults to false. If true `_includesRemovedValues` should be
46+
/// false.
4147
static var _isReadableByHost: Bool { get }
4248
}
4349

4450
extension PreferenceKey where Value: ExpressibleByNilLiteral {
51+
/// Let nil-expressible values default-initialize to nil.
4552
public static var defaultValue: Value { Value(nilLiteral: ()) }
4653
}
4754

0 commit comments

Comments
 (0)