
Swiftui Uikit Interop
Migrate an existing UIKit iOS app to SwiftUI screen-by-screen without breaking navigation or shared state.
Install
npx skills add https://github.com/dpearson2699/swift-ios-skills --skill swiftui-uikit-interopWhat is this skill?
- Screen-by-screen migration: pick leaf UIViewControllers, rewrite in SwiftUI, swap in UIHostingController at instantiatio
- UIHostingController as child view controller pattern for embedding SwiftUI inside UIKit hierarchy
- Navigation bridging between UINavigationController stacks and SwiftUI navigation
- Shared data patterns between UIKit and SwiftUI layers
- UIHostingConfiguration (iOS 16+) for UITableView and UICollectionView cells
Adoption & trust: 1.8k installs on skills.sh; 713 GitHub stars; 3/3 security scanners passed (skills.sh audits).
Recommended Skills
Vercel React Native Skillsvercel-labs/agent-skills
Firebase Basicsfirebase/agent-skills
Building Native Uiexpo/skills
Firebase Ai Logic Basicsfirebase/agent-skills
Native Data Fetchingexpo/skills
Firebase Firestorefirebase/agent-skills
Journey fit
Primary fit
UIKit-to-SwiftUI bridging is active product construction on the client, which maps to Build as the primary journey shelf. Screen UI, hosting controllers, and navigation wiring are frontend mobile work even when UIKit parents remain temporarily.
Common Questions / FAQ
Is Swiftui Uikit Interop safe to install?
skills.sh reports 3 of 3 security scanners passed. Review the Security Audits panel on this page before installing in production.
SKILL.md
READMESKILL.md - Swiftui Uikit Interop
# UIKit-to-SwiftUI Migration Patterns Patterns for incrementally migrating a UIKit app to SwiftUI. Each pattern is self-contained with rationale, implementation, and gotchas. --- ## Contents - [1. Screen-by-Screen Migration](#1-screen-by-screen-migration) - [2. UIHostingController as Child](#2-uihostingcontroller-as-child) - [3. Navigation Bridging](#3-navigation-bridging) - [4. Data Sharing Between UIKit and SwiftUI](#4-data-sharing-between-uikit-and-swiftui) - [5. UIHostingConfiguration (iOS 16+)](#5-uihostingconfiguration-ios-16) - [6. Environment Bridging](#6-environment-bridging) ## 1. Screen-by-Screen Migration Replace one `UIViewController` at a time with a `UIHostingController` wrapping a SwiftUI view. This is the safest migration path -- each screen is an isolated unit. ### Strategy 1. Pick a leaf screen (one that does not contain child view controllers). 2. Rewrite its UI in SwiftUI. 3. Replace the UIKit view controller with `UIHostingController` wherever it was instantiated. 4. Wire navigation from the parent UIKit code into the hosting controller. ### Implementation ```swift // BEFORE: UIKit screen pushed onto a navigation stack let detailVC = ItemDetailViewController(item: item) navigationController?.pushViewController(detailVC, animated: true) // AFTER: SwiftUI screen wrapped in UIHostingController let detailView = ItemDetailView(item: item) let hostingVC = UIHostingController(rootView: detailView) navigationController?.pushViewController(hostingVC, animated: true) ``` ### Passing Dismiss/Navigation Callbacks When the SwiftUI screen needs to pop itself or trigger navigation in the UIKit stack: ```swift struct ItemDetailView: View { let item: Item var onDelete: (() -> Void)? @Environment(\.dismiss) private var dismiss var body: some View { VStack { Text(item.title) Button("Delete", role: .destructive) { onDelete?() dismiss() } } } } // In UIKit: let detailView = ItemDetailView(item: item) { self.dataSource.delete(item) self.navigationController?.popViewController(animated: true) } let hostingVC = UIHostingController(rootView: detailView) ``` ### Gotchas - **Navigation bar.** `UIHostingController` inherits navigation bar visibility from its parent `UINavigationController`. Use `.navigationTitle()` and `.toolbar()` in the SwiftUI view -- they propagate to the UIKit navigation bar automatically. - **Large titles.** Set `hostingVC.navigationItem.largeTitleDisplayMode` in UIKit code if the SwiftUI `.navigationBarTitleDisplayMode()` modifier does not apply correctly. - **Tab bar insets.** `UIHostingController` respects `additionalSafeAreaInsets`. If the content overlaps the tab bar, verify safe area propagation. --- ## 2. UIHostingController as Child Embed SwiftUI sections within an existing UIKit screen. Use when migrating part of a screen (a header, a card, a section) before rewriting the entire controller. ### Implementation ```swift final class DashboardViewController: UIViewController { private var statsHostingController: UIHostingController<StatsCardView>? override func viewDidLoad() { super.viewDidLoad() let statsView = StatsCardView(stats: currentStats) let hostingVC = UIHostingController(rootView: statsView) // Enable intrinsic sizing so Auto Layout can size the hosted view if #available(iOS 16.0, *) { hostingVC.sizingOptions = [.intrinsicContentSize] } addChild(hostingVC) hostingVC.view.translatesAutoresizingMaskIntoConstraints = false containerView.addSubview(hostingVC.view) NSLayoutConstraint.activate([ hostingVC.view.topAnchor.constraint(equalTo: containerView.topAnchor), hostingVC.view.leadingAnchor.constraint(equalTo: containerView.leadingAnchor), hostingVC.view.trailingAnchor.constraint(equalTo: containerView.trailingAnchor),