Skip to content

Commit 4393a39

Browse files
authored
Merge pull request #187 from OpenSwiftUIProject/feature/hosting
Update UIHosting implementation to fix HostingExample example
2 parents 866bb21 + 9472ae3 commit 4393a39

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

42 files changed

+1616
-570
lines changed

Package.resolved

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.
Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
//
2+
// OpenSwiftUIGlue.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Empty
7+
8+
@_spi(ForOpenSwiftUIOnly)
9+
import OpenSwiftUICore
10+
11+
#if canImport(Darwin)
12+
13+
@_cdecl("OpenSwiftUIGlueClass")
14+
func OpenSwiftUIGlueClass() -> CoreGlue.Type {
15+
OpenSwiftUIGlue.self
16+
}
17+
18+
final class OpenSwiftUIGlue: CoreGlue {
19+
override func makeDefaultLayoutComputer() -> MakeDefaultLayoutComputerResult {
20+
MakeDefaultLayoutComputerResult(value: ViewGraph.current.$defaultLayoutComputer)
21+
}
22+
}
23+
24+
#endif
Lines changed: 44 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,44 @@
1+
//
2+
// HostingViewRegistry.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
// ID: 08E507B775941708E73E5FD8531D9361 (SwiftUI)
8+
9+
@_spi(Private)
10+
public import OpenSwiftUICore
11+
12+
@_spi(Private)
13+
public protocol HostingViewProtocol: AnyObject {
14+
func preferenceValue<K>(_ key: K.Type) -> K.Value where K: HostPreferenceKey
15+
func convertAnchor<Value>(_ anchor: Anchor<Value>) -> Value
16+
}
17+
18+
@_spi(Private)
19+
public class HostingViewRegistry {
20+
public static let shared: HostingViewRegistry = HostingViewRegistry()
21+
22+
public func forEach(_ body: (any HostingViewProtocol) throws -> Void) rethrows {
23+
try elements.values.forEach { box in
24+
guard let element = box.base as? HostingViewProtocol else {
25+
return
26+
}
27+
try body(element)
28+
}
29+
}
30+
31+
private var elements: [ObjectIdentifier: WeakBox<AnyObject>] = [:]
32+
33+
func add<V>(_ element: V) where V: HostingViewProtocol {
34+
elements[ObjectIdentifier(element)] = WeakBox(element)
35+
}
36+
37+
func remove<V>(_ element: V) where V: HostingViewProtocol {
38+
elements.removeValue(forKey: ObjectIdentifier(element))
39+
}
40+
}
41+
42+
@_spi(Private)
43+
@available(*, unavailable)
44+
extension HostingViewRegistry: Sendable {}
Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,39 @@
1+
//
2+
// HostingViewTransparentBackgroundReason.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
struct HostingViewTransparentBackgroundReason: OptionSet, CustomStringConvertible {
9+
var rawValue: UInt32
10+
11+
static var catalystSidebar = HostingViewTransparentBackgroundReason(rawValue: 1 << 0)
12+
static var catalystPresentation = HostingViewTransparentBackgroundReason(rawValue: 1 << 1)
13+
static var legacyPresentationSPI = HostingViewTransparentBackgroundReason(rawValue: 1 << 2)
14+
static var containerBackground = HostingViewTransparentBackgroundReason(rawValue: 1 << 3)
15+
static var listItemBackground = HostingViewTransparentBackgroundReason(rawValue: 1 << 4)
16+
17+
var description: String {
18+
var description = ""
19+
if contains(.catalystSidebar) {
20+
description.append("catalystSidebar, ")
21+
}
22+
if contains(.catalystPresentation) {
23+
description.append("catalystPresentation, ")
24+
}
25+
if contains(.legacyPresentationSPI) {
26+
description.append("legacyPresentationSPI, ")
27+
}
28+
if contains(.containerBackground) {
29+
description.append("containerBackground, ")
30+
}
31+
if contains(.listItemBackground) {
32+
description.append("listItemBackground, ")
33+
}
34+
if !description.isEmpty {
35+
description.removeLast(2)
36+
}
37+
return "[\(description)]"
38+
}
39+
}

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

Lines changed: 0 additions & 15 deletions
This file was deleted.
Lines changed: 105 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,105 @@
1+
#if os(iOS)
2+
public import UIKit
3+
4+
@available(macOS, unavailable)
5+
@available(watchOS, unavailable)
6+
@MainActor
7+
@preconcurrency
8+
open class UIHostingController<Content>: UIViewController where Content : View {
9+
var host: _UIHostingView<Content>
10+
11+
override open dynamic var keyCommands: [UIKeyCommand]? {
12+
// TODO
13+
nil
14+
}
15+
16+
public init(rootView: Content) {
17+
// TODO
18+
host = _UIHostingView(rootView: rootView)
19+
super.init(nibName: nil, bundle: nil)
20+
_commonInit()
21+
}
22+
23+
public init?(coder: NSCoder, rootView: Content) {
24+
// TODO
25+
host = _UIHostingView(rootView: rootView)
26+
super.init(coder: coder)
27+
_commonInit()
28+
}
29+
30+
public required init?(coder: NSCoder) {
31+
preconditionFailure("init(coder:) must be implemented in a subclass and call super.init(coder:, rootView:)")
32+
}
33+
34+
func _commonInit() {
35+
host.viewController = self
36+
// toolbar
37+
// toolbar.addPreferences(to: ViewGraph)
38+
// ...
39+
// IsAppleInternalBuild
40+
}
41+
42+
open override func loadView() {
43+
view = host
44+
}
45+
46+
public var rootView: Content {
47+
get { host.rootView }
48+
set { host.rootView = newValue }
49+
}
50+
51+
public var sizingOptions: UIHostingControllerSizingOptions = [] {
52+
didSet {
53+
sizingOptionsDidChange(from: oldValue)
54+
}
55+
}
56+
57+
@_spi(Private)
58+
public func setRootView(_ newRootView: Content, transaction: Transaction) {
59+
// TODO
60+
}
61+
62+
public func sizeThatFits(in size: CGSize) -> CGSize {
63+
host.sizeThatFits(size)
64+
}
65+
66+
public func _render(seconds: Double) {
67+
host.render(interval: seconds, targetTimestamp: nil)
68+
}
69+
70+
public func _forEachIdentifiedView(body: (_IdentifiedViewProxy) -> Void) {
71+
host._forEachIdentifiedView(body: body)
72+
}
73+
74+
@available(*, deprecated, message: "Use UIHostingController/safeAreaRegions or _UIHostingView/safeAreaRegions")
75+
public var _disableSafeArea: Swift.Bool {
76+
get {
77+
host.explicitSafeAreaInsets == .zero
78+
}
79+
set {
80+
host.explicitSafeAreaInsets = newValue ? .zero : nil
81+
}
82+
}
83+
84+
final public var _rendererConfiguration: _RendererConfiguration {
85+
get { host._rendererConfiguration }
86+
set { host._rendererConfiguration = newValue }
87+
}
88+
89+
final public var _rendererObject: AnyObject? {
90+
host._rendererObject
91+
}
92+
93+
func sizingOptionsDidChange(from oldSizingOptions: UIHostingControllerSizingOptions) {
94+
// TODO
95+
}
96+
}
97+
98+
@available(macOS, unavailable)
99+
extension UIHostingController {
100+
public var safeAreaRegions: SafeAreaRegions {
101+
get { host.safeAreaRegions }
102+
set { host.safeAreaRegions = newValue }
103+
}
104+
}
105+
#endif
Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
//
2+
// UIHostingControllerSizingOptions.swift
3+
// OpenSwiftUI
4+
//
5+
// Audited for iOS 18.0
6+
// Status: Complete
7+
8+
#if os(iOS)
9+
10+
/// Options for how a hosting controller tracks its content’s size.
11+
@available(macOS, unavailable)
12+
public struct UIHostingControllerSizingOptions: OptionSet, Sendable {
13+
public let rawValue: Int
14+
public init(rawValue: Int) {
15+
self.rawValue = rawValue
16+
}
17+
18+
/// The hosting controller tracks its content's ideal size in its
19+
/// preferred content size.
20+
///
21+
/// Use this option when using a hosting controller with a container view
22+
/// controller that requires up-to-date knowledge of the hosting
23+
/// controller's ideal size.
24+
///
25+
/// - Note: This option comes with a performance cost because it
26+
/// asks for the ideal size of the content using the
27+
/// ``ProposedViewSize/unspecified`` size proposal.
28+
public static let preferredContentSize: UIHostingControllerSizingOptions = .init(rawValue: 1 << 0)
29+
30+
/// The hosting controller's view automatically invalidate its intrinsic
31+
/// content size when its ideal size changes.
32+
///
33+
/// Use this option when the hosting controller's view is being laid out
34+
/// with Auto Layout.
35+
///
36+
/// - Note: This option comes with a performance cost because it
37+
/// asks for the ideal size of the content using the
38+
/// ``ProposedViewSize/unspecified`` size proposal.
39+
public static let intrinsicContentSize: UIHostingControllerSizingOptions = .init(rawValue: 1 << 1)
40+
}
41+
42+
#endif

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

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

0 commit comments

Comments
 (0)