Swiftui uikit interop skill
Use this skill to bridge SwiftUI and UIKit in either direction. Embed SwiftUI in a UIKit app -- present or child-embed a UIHostingController, put SwiftUI in UICollectionView/UITableView cells via UIHostingConfiguration, or build a widget / Live Activity. Wrap UIKit for use in SwiftUI -- UIViewRepresentable / UIViewControllerRepresentable with a Coordinator for delegates and data sources. Pass data and state across the boundary (init params, @Binding, closures, environment/trait forwarding), fix hosting-controller sizing, and migrate a UIKit AppDelegate/SceneDelegate app incrementally to the SwiftUI App lifecycle. Trigger even when the user doesn't say "interop" -- e.g. "show this SwiftUI screen from my view controller", "use my UIKit map view in SwiftUI", "put SwiftUI in a collection view cell". Do NOT use for pure SwiftUI view code (swiftui-expert), app architecture / composition root (ios-architecture-expert), or general Swift language questions (swift-language-expert).From its SKILL.md
npx -y skills add SwiftyJourney/swiftui-uikit-interop-skillAssembled from the repository path, not quoted from the project. Check it against their README if it does not work.
One thing to look at
- 0 stars0 stars. Stars are a popularity signal and not a quality one, but at this level it is likely that nobody has read this closely except its author, and you would be relying on your own review.
SKILL.md
7.0 KB, ~1.4k tokens by cl100k_base, as published. Nobody here has run it
SwiftUI ⇄ UIKit Interop
This skill covers the boundary between SwiftUI and UIKit — embedding one inside the other and passing data across. It does not cover pure-SwiftUI view design (use swiftui-expert) or the app's dependency graph (use ios-architecture-expert).
Agent Behavior Contract
When this skill is active, follow these rules strictly:
- This skill is only about the boundary. Pure SwiftUI view code → defer to
swiftui-expert; app architecture / composition root / DI → defer toios-architecture-expert. - Wrap UIKit in SwiftUI with a representable —
UIViewRepresentablefor a view,UIViewControllerRepresentablefor a view controller. Never new up a UIKit view directly inside a SwiftUIbody. - Route all UIKit delegate / data-source / target-action callbacks through a
Coordinator(makeCoordinator()), never store mutable UIKit state on the representable struct. - Data flows one way per direction: SwiftUI state →
updateUIView/updateUIViewController; UIKit events →Coordinator→@Binding/closure. Don't mutate SwiftUI state synchronously from insideupdateUIView. - Embed SwiftUI in UIKit with
UIHostingController— and when embedding (not presenting), add it as a child view controller (addChild/didMove(toParent:)), not just itsview. - Use
UIHostingConfigurationfor SwiftUI in collection/table cells (iOS 16+) — one configuration per cell, not aUIHostingControllerper cell. - Keep hosting sizing correct — set
sizingOptions/ honorintrinsicContentSize/safeAreaRegionsso Auto Layout and self-sizing cells measure the SwiftUI content. - Gate version-specific APIs (
UIHostingConfigurationiOS 16,UIHostingController.sizingOptionsiOS 16, trait-bridged environment iOS 17,@UIApplicationDelegateAdaptorlifecycle) with#available/@available.
Interop Diagnostic Table
| Symptom | First check | Smallest fix | Deep dive |
|---|---|---|---|
| Show a SwiftUI screen from a UIKit view controller | Present vs embed | Present a UIHostingController | references/hosting-controller.md |
| Embed a SwiftUI view inside an existing UIKit screen | Child VC containment | Add UIHostingController as a child VC | references/hosting-controller.md |
| SwiftUI content in a collection/table cell | Cell configuration | UIHostingConfiguration (iOS 16+) | references/hosting-configuration.md |
| Use a UIKit view (map, camera, web) in SwiftUI | View wrapping | UIViewRepresentable + Coordinator | references/representables.md |
| Use a UIKit view controller in SwiftUI | VC wrapping | UIViewControllerRepresentable + Coordinator | references/representables.md |
| Delegate/data-source callbacks from wrapped UIKit | Callback routing | Route through the Coordinator | references/representables.md |
| Pass data/state between SwiftUI and UIKit | Direction of flow | init params + @Binding/closures; forward environment via traits | references/passing-data-across-the-boundary.md |
| Hosted SwiftUI doesn't resize / clips / fights Auto Layout | Hosting sizing | sizingOptions / intrinsic size / safe-area | references/hosting-controller.md |
| SwiftUI in a widget or Live Activity | Extension target | WidgetKit + SwiftUI | references/widgets-and-live-activities.md |
| Move a UIKit app onto the SwiftUI lifecycle | Incremental migration | Adopt App/Scene, bridge with delegate adaptors | references/lifecycle-migration.md |
Direction Decision Tree
- Which framework owns the screen you're adding to?
- UIKit owns it, you're adding SwiftUI → embed (
UIHostingController, orUIHostingConfigurationfor cells) - SwiftUI owns it, you need a UIKit view/VC → wrap (
UIViewRepresentable/UIViewControllerRepresentable)
- UIKit owns it, you're adding SwiftUI → embed (
- Is it a whole screen or a piece? Whole screen → present/push a hosting controller or a representable VC. A piece → child-embed a hosting controller, or wrap a single UIKit view.
- Does the UIKit side report events back? → add a
Coordinatorand bridge via@Binding/closures. - Crossing the lifecycle? Migrating the app entry point →
references/lifecycle-migration.md.
Guardrails
- Do not instantiate UIKit views/VCs directly in a SwiftUI
body— wrap them in a representable - Do not put delegate/data-source conformance on the representable struct — use the
Coordinator(a class) - Do not mutate
@State/@Bindingsynchronously insideupdateUIView/updateUIViewController(causes update loops) — dispatch or guard for actual change - Do not add a hosting controller's
viewas a subview without also doing child-VC containment (addChild/didMove) — you lose lifecycle and safe-area forwarding - Do not create a
UIHostingControllerper cell — useUIHostingConfiguration - Do not solve app architecture/DI here — that is
ios-architecture-expert's job - Do not re-teach pure SwiftUI patterns — defer to
swiftui-expert
Reference Router
Open the smallest reference that matches the task:
- Embedding SwiftUI in UIKit
- hosting-controller.md —
UIHostingController: present, child-embed, subclass, sizing - hosting-configuration.md —
UIHostingConfigurationfor collection/table cells (iOS 16+)
- hosting-controller.md —
- Wrapping UIKit in SwiftUI
- representables.md —
UIViewRepresentable,UIViewControllerRepresentable, theCoordinatorpattern
- representables.md —
- Crossing the boundary
- passing-data-across-the-boundary.md — init params,
@Binding, closures, environment/trait forwarding, observation
- passing-data-across-the-boundary.md — init params,
- Extensions
- widgets-and-live-activities.md — SwiftUI in WidgetKit widgets and Live Activities
- Migration
- lifecycle-migration.md — moving a UIKit
AppDelegate/SceneDelegateapp to the SwiftUIApplifecycle
- lifecycle-migration.md — moving a UIKit