diff --git a/Example/HostingExample/ViewController.swift b/Example/HostingExample/ViewController.swift index 7c5d98175..4e83c8a7d 100644 --- a/Example/HostingExample/ViewController.swift +++ b/Example/HostingExample/ViewController.swift @@ -14,13 +14,61 @@ import SwiftUI class ViewController: UINavigationController { override func viewDidAppear(_ animated: Bool) { - let vc = UIHostingController(rootView: ContentView()) - pushViewController(vc, animated: false) + pushViewController(EntryViewController(), animated: false) } } +final class EntryViewController: UIViewController { + override func viewDidLoad() { + navigationItem.rightBarButtonItem = UIBarButtonItem( + title: "Push", + style: .plain, + target: self, + action: #selector(pushHostingVC) + ) + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + self.pushHostingVC() + } + } + + @objc + private func pushHostingVC() { + guard let navigationController else { return } + let hostingVC = UIHostingController(rootView: ContentView()) + navigationController.pushViewController(hostingVC, animated: true) + } +} + +// TODO: Known issue +// 1. State toggle crash +// 2. pop - UIHostingView deinit crash / onDisappear +// 3. if else builder issue struct ContentView: View { + @State private var first = true + var body: some View { - AnyView(EmptyView()) + if first { + Color.red + .onAppear { + print("Red appear") + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + first.toggle() + } + } + .onDisappear { + print("Red disappear") + } + } else { + Color.blue + .onAppear { + print("Blue appear") + DispatchQueue.main.asyncAfter(deadline: .now() + 1) { + first.toggle() + } + } + .onDisappear { + print("Blue disappear") + } + } } } diff --git a/Sources/OpenSwiftUI/Core/Modifier/SceneModifier/TODO/_SceneModifier.swift b/Sources/OpenSwiftUI/Core/Modifier/SceneModifier/TODO/_SceneModifier.swift index a0e37d23a..b26525a06 100644 --- a/Sources/OpenSwiftUI/Core/Modifier/SceneModifier/TODO/_SceneModifier.swift +++ b/Sources/OpenSwiftUI/Core/Modifier/SceneModifier/TODO/_SceneModifier.swift @@ -22,6 +22,6 @@ extension _SceneModifier { extension _SceneModifier where Body == Never { @inline(__always) public func body(content _: SceneContent) -> Body { - preconditionFailure("body() should not be called on \(Self.self)") + preconditionFailure("body() should not be called on \(Self.self).") } } diff --git a/Sources/OpenSwiftUI/Scene/Core/Scene.swift b/Sources/OpenSwiftUI/Scene/Core/Scene.swift index b79701071..c15499bc9 100644 --- a/Sources/OpenSwiftUI/Scene/Core/Scene.swift +++ b/Sources/OpenSwiftUI/Scene/Core/Scene.swift @@ -16,6 +16,6 @@ extension Never: Scene {} extension Scene { func sceneBodyError() -> Never { - preconditionFailure("body() should not be called on \(Self.self)") + preconditionFailure("body() should not be called on \(Self.self).") } } diff --git a/Sources/OpenSwiftUICore/Graphic/Color/ColorView.swift b/Sources/OpenSwiftUICore/Graphic/Color/ColorView.swift index d3679f960..fec617ffe 100644 --- a/Sources/OpenSwiftUICore/Graphic/Color/ColorView.swift +++ b/Sources/OpenSwiftUICore/Graphic/Color/ColorView.swift @@ -3,17 +3,39 @@ // OpenSwiftUICore // // Audited for iOS 18.0 -// Empty +// Status: Empty -@MainActor -@preconcurrency -package struct ColorView: PrimitiveView { //FIXME +package import Foundation + +package struct ColorView: RendererLeafView, Animatable { package var color: Color.Resolved package init(_ color: Color.Resolved) { self.color = color } - @available(iOS 13.0, tvOS 13.0, watchOS 6.0, macOS 10.15, *) - package typealias Body = Swift.Never + nonisolated package static func _makeView(view: _GraphValue, inputs: _ViewInputs) -> _ViewOutputs { + var inputs = inputs + if inputs.base.options.isEmpty { + // TODO: AnimatableAttribute + } + return makeLeafView(view: view, inputs: inputs) + } + + package var descriptionAttributes: [(name: String, value: String)] { + preconditionFailure("TODO") + } + + package func contains(points: [PlatformPoint], size: CGSize) -> BitVector64 { + preconditionFailure("TODO") + } + + package func content() -> DisplayList.Content.Value { + preconditionFailure("TODO") + } + + package var animatableData: Color.Resolved.AnimatableData { + get { color.animatableData } + set { color.animatableData = newValue } + } } diff --git a/Sources/OpenSwiftUICore/Modifier/ViewModifier/ViewModifier.swift b/Sources/OpenSwiftUICore/Modifier/ViewModifier/ViewModifier.swift index b0586977f..ca04f9f05 100644 --- a/Sources/OpenSwiftUICore/Modifier/ViewModifier/ViewModifier.swift +++ b/Sources/OpenSwiftUICore/Modifier/ViewModifier/ViewModifier.swift @@ -137,7 +137,7 @@ extension ViewModifier where Self: _GraphInputsModifier, Body == Never { extension ViewModifier { func bodyError() -> Never { - preconditionFailure("body() should not be called on \(Self.self)") + preconditionFailure("body() should not be called on \(Self.self).") } } diff --git a/Sources/OpenSwiftUICore/Render/RendererLeafView.swift b/Sources/OpenSwiftUICore/Render/RendererLeafView.swift new file mode 100644 index 000000000..15f40430d --- /dev/null +++ b/Sources/OpenSwiftUICore/Render/RendererLeafView.swift @@ -0,0 +1,28 @@ +// +// RendererLeafView.swift +// OpenSwiftUICore +// +// Audited for iOS 18.0 +// Status: WIP + +import Foundation + +package protocol RendererLeafView: /*ContentResponder,*/ PrimitiveView, UnaryView { + static var requiresMainThread: Bool { get } + func content() -> DisplayList.Content.Value +} + +extension RendererLeafView { + package static var requiresMainThread: Swift.Bool { + false + } + + func contains(points: [PlatformPoint], size: CGSize) -> BitVector64 { + preconditionFailure("TODO") + } + + package static func makeLeafView(view: _GraphValue, inputs: _ViewInputs) -> _ViewOutputs { + // preconditionFailure("TODO") + _ViewOutputs() + } +} diff --git a/Sources/OpenSwiftUICore/View/View.swift b/Sources/OpenSwiftUICore/View/View.swift index 9b6cf3781..a0ace638a 100644 --- a/Sources/OpenSwiftUICore/View/View.swift +++ b/Sources/OpenSwiftUICore/View/View.swift @@ -106,7 +106,7 @@ extension PrimitiveView { extension View { package func bodyError() -> Never { - preconditionFailure("body() should not be called on \(Self.self)") + preconditionFailure("body() should not be called on \(Self.self).") } } diff --git a/Sources/OpenSwiftUICore/View/ViewBuilder.swift b/Sources/OpenSwiftUICore/View/ViewBuilder.swift index 549792aa0..94585e750 100644 --- a/Sources/OpenSwiftUICore/View/ViewBuilder.swift +++ b/Sources/OpenSwiftUICore/View/ViewBuilder.swift @@ -1,16 +1,23 @@ // // ViewBuilder.swift -// OpenSwiftUI +// OpenSwiftUICore // -// Audited for RELEASE_2023 +// Audited for iOS 18.0 // Status: Complete @resultBuilder -public enum ViewBuilder { +public struct ViewBuilder { @_alwaysEmitIntoClient public static func buildExpression(_ content: Content) -> Content where Content: View { content } + + @available(*, unavailable, message: "this expression does not conform to 'View'") + @_disfavoredOverload + @_alwaysEmitIntoClient + public static func buildExpression(_ invalid: Any) -> some View { + fatalError() + } @_alwaysEmitIntoClient public static func buildBlock() -> EmptyView { @@ -30,7 +37,7 @@ public enum ViewBuilder { } @available(*, unavailable) -extension ViewBuilder: Swift.Sendable {} +extension ViewBuilder: Sendable {} extension ViewBuilder { @_alwaysEmitIntoClient