From 503c3b893e8ca5e72ae4f5f79803ee2c7f254bb4 Mon Sep 17 00:00:00 2001 From: Kyle Date: Thu, 19 Mar 2026 02:03:34 +0800 Subject: [PATCH] Fix Xcode Preview rendering by disabling waitingForPreviewThunks PreviewsInjection.framework calls SwiftUI.__previewThunksHaveFinishedLoading() via a library-specific GOT binding (two-level namespace) after loading preview dylibs. OpenSwiftUI's version is never called since the binding targets SwiftUI specifically. Disable the blocking gate and implement the full unblocking logic for when OpenSwiftUI adds its own preview thunk system in the future. --- Example/Shared/PreviewShims.swift | 40 +++++++++++++++++++ Sources/OpenSwiftUICore/Graph/GraphHost.swift | 21 ++++++++-- 2 files changed, 58 insertions(+), 3 deletions(-) create mode 100644 Example/Shared/PreviewShims.swift diff --git a/Example/Shared/PreviewShims.swift b/Example/Shared/PreviewShims.swift new file mode 100644 index 000000000..cf931a95a --- /dev/null +++ b/Example/Shared/PreviewShims.swift @@ -0,0 +1,40 @@ +// +// PreviewShims.swift +// Shared + +import OpenSwiftUI +import SwiftUI + +// Helper method before we add fully preview thunk and preview macro support for OpenSwiftUI + +#if canImport(AppKit) && !targetEnvironment(macCatalyst) +import AppKit +extension OpenSwiftUI.View { + func _previewVC() -> some NSViewController { + OpenSwiftUI.NSHostingController(rootView: self) + } +} +extension SwiftUI.View { + func _previewVC() -> some NSViewController { + SwiftUI.NSHostingController(rootView: self) + } +} +#else +import UIKit +extension OpenSwiftUI.View { + func _previewVC() -> some UIViewController { + OpenSwiftUI.UIHostingController(rootView: self) + } +} +extension SwiftUI.View { + func _previewVC() -> some UIViewController { + SwiftUI.UIHostingController(rootView: self) + } +} +#endif + +#Preview { + // FIXME: Not working on macOS yet + ContentView() + ._previewVC() +} diff --git a/Sources/OpenSwiftUICore/Graph/GraphHost.swift b/Sources/OpenSwiftUICore/Graph/GraphHost.swift index f9fe17e4b..f67f7b82c 100644 --- a/Sources/OpenSwiftUICore/Graph/GraphHost.swift +++ b/Sources/OpenSwiftUICore/Graph/GraphHost.swift @@ -690,11 +690,26 @@ extension Graph { } } -// MARK: - Preview +// MARK: - Preview [6.5.4] private var blockedGraphHosts: [Unmanaged] = [] -private let waitingForPreviewThunks = EnvironmentHelper.bool(for: "XCODE_RUNNING_FOR_PREVIEWS") +// NOTE: In SwiftUI, PreviewsInjection.framework's DYLDDynamicProductLoader calls +// SwiftUI.__previewThunksHaveFinishedLoading() via a library-specific GOT binding after +// all preview dylibs are dlopen'd. This unblocks graph instantiation for waiting hosts. +// Since the binding targets SwiftUI specifically (two-level namespace), OpenSwiftUI's +// version is never called. We disable the blocking to allow graph instantiation in Preview. +// TODO: Re-enable when OpenSwiftUI implements its own preview thunk registration system. +private var waitingForPreviewThunks = false // EnvironmentHelper.bool(for: "XCODE_RUNNING_FOR_PREVIEWS") public func __previewThunksHaveFinishedLoading() { - _openSwiftUIUnimplementedFailure() + guard waitingForPreviewThunks else { return } + waitingForPreviewThunks = false + let hosts = blockedGraphHosts + blockedGraphHosts = [] + for host in hosts { + let graphHost = host.takeUnretainedValue() + if let graphDelegate = graphHost.graphDelegate { + graphDelegate.graphDidChange() + } + } }