SuperAPI AI Directory

swiftui-uikit-interop

Coding & development

View repository

Updated 10-16 05:53

About this skill

SwiftUI-UIKit Interop

Bridge UIKit and SwiftUI in both directions: wrap UIKit views and controllers for use in SwiftUI, embed SwiftUI views into existing UIKit view hierarchies, and coordinate state updates safely. Targets Swift 6.3 / iOS 26+.

Contents

  • Bridging Directions
  • Representable Lifecycle and Coordinator
  • State Synchronization and Feedback Loops
  • Embedding SwiftUI in UIKit
  • Route by Task
  • Common Mistakes
  • Review Checklist
  • References

Bridging Directions

  1. UIKit into SwiftUI:
    • UIViewRepresentable: Wraps a custom UIView (e.g., text views, maps, custom controls).
    • UIViewControllerRepresentable: Wraps a UIViewController (e.g., camera controllers, document pickers, share sheets).
  2. SwiftUI into UIKit:
    • UIHostingController: Embeds SwiftUI views into UIKit view controller hierarchies.
    • UIHostingConfiguration: Embeds SwiftUI views directly into UICollectionView and UITableView cells (iOS 16+).

Representable Lifecycle and Coordinator

makeCoordinator() ──> makeUIView(context:) ──> updateUIView(uiView, context:) ──> dismantleUIView(uiView, coordinator:)
  • makeCoordinator(): Called once to create the delegate/coordinator object.
  • makeUIView(context:): Called once to instantiate the UIKit view and assign delegates.
  • updateUIView(_:context:): Called on every SwiftUI state change affecting the view. Must be idempotent.
  • dismantleUIView(_:coordinator:): Cleanup point when the view leaves the hierarchy. Invalidate timers, unregister observers.

State Synchronization and Feedback Loops

[!WARNING] Prevent infinite update cycles: When UIKit notifies the coordinator of a change (e.g., textViewDidChange), the coordinator updates SwiftUI state via @Binding. This triggers updateUIView. Always check for value equality before applying updates to the UIKit view:

if uiView.text != text { uiView.text = text }

Embedding SwiftUI in UIKit

When adding a UIHostingController as a child view controller:

  1. addChild(hostingController)
  2. view.addSubview(hostingController.view)
  3. Set Auto Layout constraints
  4. hostingController.didMove(toParent: self)

Use UIHostingConfiguration for modern cell layouts in UICollectionView/UITableView without manual controller management.

Route by Task

Common Mistakes

  • Re-creating heavy UIKit objects inside updateUIView instead of configuring the existing instance.
  • Omitting equality checks in updateUIView, triggering continuous render feedback loops.
  • Adding a UIHostingController's view without calling addChild and didMove(toParent:).
  • Forgetting to clean up delegates, KVO, or NotificationCenter observers in dismantleUIView.
  • Ignoring safe area insets and sizing calculations (sizeThatFits) in custom representables.

Review Checklist

  • makeCoordinator used for delegates, target-actions, and data sources
  • updateUIView guards against redundant assignments to avoid feedback loops
  • Child view controller containment calls (addChild, didMove) properly paired
  • Cell layouts in UIKit use UIHostingConfiguration where available
  • Subscribed observers and display links invalidated in dismantleUIView
  • Auto Layout constraints configured with translatesAutoresizingMaskIntoConstraints = false

References