SwiftUI

SwiftUI is Apple’s declarative UI framework. tswift renders it without a Swift toolchain, LLVM, or native compilation: the interpreter instantiates a View, runs body, produces a host-neutral UIIR view tree, diffs it into a patch stream, and a dependency-free host applies those patches to real UI.

Current status: foundational tiers shipped. The Counter slice (v1) plus Tiers 2–5 — composition, dynamic collections, input controls, and observation — are implemented and gated by deterministic goldens. Async (Tier 6), layout / geometry (Tier 7), and navigation (Tier 8) are not started.

The surface number counts individual API members across the iOS SDK SwiftUI interface; it is low because each shipped view exposes many initializers and modifiers we don’t need yet. The functional coverage — enough to render and interact with real view hierarchies — is much further along, as the tiers below show.


How it renders

    
flowchart LR
  src["Swift View\nsource"]
  interp["Interpreter\n+ tswift-swiftui\nbuiltins"]
  tree["Render-node tree\n(owns @State,\nkeyed identity)"]
  uiir["UIIR\nview tree"]
  diff["Rust diff\nengine"]
  host["Host applier\n(web + iOS)"]

  src --> interp --> tree --> uiir --> diff --> host
  host -- "events" --> interp

  style src   fill:#1a0d2e,stroke:#a855f7,color:#eeeef5
  style host  fill:#0d2e1a,stroke:#34c759,color:#eeeef5

  
tswift SwiftUI pipeline (shipped through Tier 5)

The same patch protocol drives two hosts: the web <swiftui-canvas> custom element, and a native iOS SwiftUI applier used for screenshot verification.


Tier roadmap

Tier Mechanism Status
v1 Counter slice — VStack/Text/Button, @State, modifiers, full render→diff→patch loop
Tier 2 View composition & demo tabs (Greeting/Stack/Profile) — HStack/ZStack/Spacer, shapes, Toggle
Tier 3 Dynamic collections & identity — List/Section/ForEach, keyed diff with move/insert/remove
Tier 4 Bindings & input controls — TextField/SecureField/Slider/Stepper/Picker
Tier 5 Observation & shared model — ObservableObject/@Published/@StateObject/@EnvironmentObject 🟡
Tier 6 Task & async push channel
Tier 7 Layout & geometry — GeometryReader, alignment
Tier 8 Navigation & presentation — NavigationStack, sheets

Tier 5 is partial: observation is implemented; @Environment(\.keyPath) is the one deferred item.


Views & controls implemented

Category Types
Layout VStack ✅ · HStack ✅ · ZStack ✅ · Spacer
Collections List ✅ · Section ✅ · ForEach
Text & actions Text ✅ · Button ✅ · Toggle
Input controls TextField ✅ · SecureField ✅ · Slider ✅ · Stepper ✅ · Picker
Shapes Circle ✅ · Rectangle ✅ · RoundedRectangle ✅ · Capsule ✅ · Ellipse
Not started ScrollView ⬜ · Grid/LazyVGrid ⬜ · NavigationStack ⬜ · TabView ⬜ · Form ⬜ · GeometryReader ⬜ · AsyncImage ⬜ · ProgressView

Modifiers: font, fontWeight, foregroundColor, padding, background, cornerRadius, frame, fill, and tag are wired through to both hosts. Semantic colors (.primary/.secondary) and the system background adapt to light/dark.


Verification

Every slice is checked by an autonomous loop — no Apple toolchain required to gate a change.

Layer What it checks Status
A — Surface API inventory vs the iOS SDK SwiftUI interface
B — UIIR goldens initial render produces the exact expected view tree
C — Interaction goldens events produce the exact expected patch stream
D — Screenshot diff render UIIR to real SwiftUI (iOS) and the web host, screenshot both 🟡

Layer D runs both halves locally today: a native UiirRenderer SwiftPM package builds real SwiftUI from the UIIR fixtures and snapshots them, and a Playwright harness drives the <swiftui-canvas> element through the same mount → applyPatches loop. Both capture a device × appearance matrix (iPhone + iPad, light + dark), so token/CSS drift between the web and native renderers is surfaced side by side. Perceptual-diff tooling and a CI job are the remaining pieces.


What you can run now

Try it in the Playground →