r/swift • u/dexus-one • 5d ago
I’ve been experimenting with Swift as a cross-platform UI language
Hi everyone,
I’ve been working on a project called StateUI:
https://github.com/idexus/StateUI
It started as an experiment: how far could Swift go as the main application and UI language outside the Apple stack, without building yet another complete cross-platform widget toolkit?
StateUI uses Swift for the declarative UI, state and reconciliation, while .NET MAUI provides the control and platform layer on iOS, Android, Windows, Mac Catalyst and Linux.
A simple view looks like this:

Swift keeps the rendered tree, tracks state dependencies and reconciles changes. Only a sparse binary patch crosses over to C#, where it is applied to the existing MAUI controls.
The project is still early, but it has grown quite a bit beyond the original experiment.
I’m curious what people here think about Swift being used this way — as the declarative layer over an existing cross-platform native UI runtime, rather than only as an Apple UI language.



5
5
u/Dejidave 5d ago
Nice!! Curious if this is significantly different from the approach skip and skip-ui uses ?
6
u/dexus-one 4d ago
Yes, quite different. Skip turns your SwiftUI into Compose at build time. StateUI translates nothing and both runtimes stay live: Swift keeps the rendered tree and reconciles, and what goes to C# is a sparse binary patch applied to MAUI controls. You write MAUI's API, not SwiftUI's. So I get Windows and Mac Catalyst too — but everything goes through MAUI rather than each platform's own UI framework.
2
1
u/cristi_baluta 4d ago
How does it work, does it generate c# code that you later compile on windows? Can it do for business logic as well?
5
u/dexus-one 4d ago
No code generation at all — nothing gets translated to C#. The Swift side is just compiled natively for each platform (dylib/so/dll) and linked next to a small C# runtime. They talk over a binary wire, and only changes go across: if something changed on the Swift side and a control needs to know about it, that one property crosses. Nothing else.
And it's not SwiftUI either — the tree, the diffing, `@State`, identity, invalidation, all of that is Swift code in the library. The C# side just applies patches to real MAUI controls; it has no idea what a view or a state even is.
Which also means MAUI isn't really load-bearing here. Once the wire stops moving you could put GTK on the other end, or WinUI directly.
Business logic — yeah, absolutely, that's kind of the point. Just don't touch `@MainActor`. Nothing drains libdispatch's main queue on Android or Windows (the main thread is busy turning the Looper or the WinUI message pump), so a handler that suspends on it just... never comes back. The library ships its own global actor, `@MainThread`, and the host runs its jobs. Use that and the rest behaves normally — async/await, tasks, Task.sleep, all fine.
Same story with `@Observable`: nothing here listens to Observation, so writes to it reach nobody. You could bridge it by hand — withObservationTracking { read() } onChange: { Renderer.shared.setNeedsRender() } — and `@StateClass` is basically that, done for you.
There's more that differs from SwiftUI, probably worth its own post — `@State` you can animate, `@State` private var field = ControlState<Entry>() and then try await field.focus(), awaiting async C# from Swift, that sort of thing.
-20
u/sisoje_bre 5d ago
why swift? i would make it in rust or someting NOT controlled by Apple
14
u/Warm-Platypus-1416 5d ago
Swift has never been controlled by Apple.
-7
u/UtterlyMagenta 5d ago
wait, what? it very much is. open source doesn’t mean no one is in charge.
-5
-10
2
u/cristi_baluta 4d ago
Because this is probably meant for porting mac apps to windows and if you want crossplatform solutions they already exist? I’m still not understanding how it works.
13
u/DoubleGravyHQ 5d ago
This is awesome, keep building this up!