Merged
Conversation
The generated bridge previously wrapped every preview body in a @ViewBuilder func __previewBody() -> some SwiftUI.View, which failed to compile when the body returned a UIView or UIViewController: error: static method 'buildExpression' requires that 'ExampleUIView' conform to 'View' Xcode's first-party #Preview macro sidesteps this with overloaded body parameters for View, UIView, and UIViewController. This change adds the same overload set at the generator layer: the new PreviewBridgeSource template emits __PreviewBridge.wrap(_:) with a @ViewBuilder generic overload for SwiftUI views and non-generic overloads for UIView and UIViewController that auto-wrap in UIViewRepresentable / UIViewControllerRepresentable. Swift's overload resolution picks the right wrapping based on the body's return type. Scope is UIKit-only (iOS). AppKit bodies on macOS remain out of scope until anyone asks. The helper is platform-gated at generation time via PreviewPlatform rather than #if canImport(UIKit), because UIKit is visible on macOS SDKs for Catalyst interop. Full-pipeline compile tests cover UIView, UIViewController, and a SwiftUI-on-iOS regression guard. Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
The reported failure form was `#Preview { ExampleUIView(deps: deps) }`
wrapped inside `withDependencies`. The existing `fullPipelineUIViewBody`
test uses a zero-arg init, which exercises the same overload path but
doesn't mirror the shape that originally broke. Adds a targeted test
that wraps `ExampleUIView(label:)` in a helper closure — same structural
pattern as the user's `withDependencies` case, without pulling in the
swift-dependencies package as a test dependency.
Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#Preview { ExampleUIView() }blocks failed to compile because the generated bridge wrapped every body in a@ViewBuilder func __previewBody() -> some SwiftUI.View, which rejectsUIView/UIViewControllerreturns.PreviewBridgeSourcetemplate emits__PreviewBridge.wrap(_:)with a@ViewBuildergeneric overload forSwiftUI.Viewplus non-generic overloads forUIView/UIViewControllerthat auto-wrap inUIViewRepresentable/UIViewControllerRepresentable. Swift's overload resolution picks the right path from the body's return type — same approach Xcode's first-party#Previewmacro uses.PreviewPlatformrather than#if canImport(UIKit)because UIKit is visible on macOS SDKs for Catalyst interop. AppKit bodies on macOS remain out of scope.Why
Reported failure when rendering
#Preview { ExampleUIView(deps: deps) }insidewithDependencies:error: static method 'buildExpression' requires that 'ExampleUIView' conform to 'View'. The@ViewBuilderwrapper Swift-constrained every preview body to SwiftUI views even though many users write UIKit previews.Known limitations (same as Xcode's
#Previewfor UIKit)return— UIKit has no@ViewBuilderequivalent.UIViewsubclass that also conforms toSwiftUI.Viewwould be ambiguous; left undocumented to avoid@_disfavoredOverload(an underscore-prefixed compiler-internal attribute).any UIKitProtocol) won't be auto-wrapped; users can add an explicit representable.Test plan
swift test --filter PreviewsCoreTests— 207 tests green (204 pre-existing + 3 new).platform: .iOSbodies:fullPipelineUIViewBody—#Preview { ExampleUIView() }fullPipelineUIViewControllerBody—#Preview { ExampleVC() }fullPipelineSwiftUIBodyIOS— regression guard that SwiftUI bodies still compile via the new__PreviewBridge.wrappath.fullPipelineWithIfAvailableandfullPipelineWithMultiStatementstill pass unchanged (preserve@ViewBuildersemantics:if #available, leadinglet, branches with different concrete types).examples/spm/Sources/ToDo/UIKitPreview.swiftadded as an end-to-end fixture; builds cleanly on macOS (guarded with#if canImport(UIKit))./integration-testagainst the iOS simulator to render the new UIKit example end-to-end.🤖 Generated with Claude Code