Skip to content

Improve interoperability with native UI frameworks #202

New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Draft
wants to merge 3 commits into
base: main
Choose a base branch
from

Conversation

stackotter
Copy link
Owner

This PR introduces various APIs related to improving interoperability between SwiftCrossUI view code and native UI frameworks. This includes:

  • Making it easier to make platform-specific modifications to the native widgets behind SwiftCrossUI views via the inspect family of modifiers
    • This allows people to work around missing SwiftCrossUI features and to access niche platform-specific APIs that we don't plan on wrapping
  • Enabling the hosting of SwiftCrossUI views in native apps via the FooHostingView family of types
  • Enabling the hosting of native views in SwiftCrossUI apps via the FooRepresentable family of types
    • (SwiftCrossUI already NSViewRepresentable, UIViewRepresentable and UIViewControllerRepresentable, but we still need to introduce similar APIs for the non-Apple backends)

So far I've completed the inspect family of view modifiers (which are housed in each backend), and introduced an AdvancedCustomizationExample app to showcase these new advanced customization APIs.

@stackotter stackotter force-pushed the backend_interop branch 3 times, most recently from 40ce4d3 to 2407a98 Compare June 26, 2025 07:41
These changes make platform-specific native customizations significantly
easier to perform. Hopefully this will make SwiftCrossUI significantly
more viable for actual production apps that often just need to get
things working even if there's not a nice neat first party API for it
yet.

Inspiration was taken from swiftui-introspect.
@stackotter
Copy link
Owner Author

I've created the FooRepresentable family of protocols now. Next I'll working on the FooHostingView family of views and then I'll come back and try to improve the experience of using the FooRepresentable protocols. The naming of the protocol requirements currently differ in just enough ways to be annoying when copy and pasting an existing implementation to adapt it for a new backend. Some suggestions were given in the Discord server that I'm considering going with.

The hardest part of implementing the FooRepresentable family of protocols was integrating with the layout system of the underlying native frameworks. Each framework exposes a different measurement API with unique limitations. The WinUI one is probably the most fragile because I had to apply a similar hack to the one used to get natural sizing working correctly; any WinUI elements that SwiftCrossUI itself doesn't already use are likely to have incorrect sizes before the first render. The other dodgy implementation is the GtkBackend one. It seems to work well enough, but throws a bunch of warnings because we occasionally measure with less height/width than the underlying widget can work with. I've searched around for APIs that would tell us what these minimum workable dimensions are, but I haven't found any yet. The issue is that when measuring you provide one dimension and get minimum/natural dimensions for the other dimension, but Gtk never actually tells you how much of the provided dimension it wants to use. Gtk 3 doesn't seem to care.

@stackotter stackotter force-pushed the backend_interop branch 2 times, most recently from fee3448 to 288ce91 Compare July 10, 2025 03:57
The Swift Package Collection signing certificate used by Xcode 15.4
expired 10 hours ago and broke any workflows that used xcodebuild (for
SwiftCrossUI's CI at least). It's probably a good that that all
platforms are getting tested against the same Swift version now anyway.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

1 participant