Skip to content
Prepare to Grow

UIKit Development

Integrating UIKit with SwiftUI

Adopt frameworks incrementally with hosting controllers, representables, coordinators, and one-way state synchronization.

Intermediate5 min read2 guided activities

Before you begin

What you will understand

  • Host SwiftUI content inside UIKit.
  • Wrap UIKit views and controllers for SwiftUI.
  • Use a coordinator for delegate callbacks.
  • Avoid state loops and competing layout ownership.
01

Learning stage

Concept Explanation

UIKit and SwiftUI can coexist feature by feature. UIHostingController wraps a SwiftUI hierarchy as a normal view controller that UIKit can push, present, or contain. This makes incremental adoption possible without rebuilding navigation and services at once.

UIViewRepresentable and UIViewControllerRepresentable expose UIKit objects to SwiftUI. The make method creates the object once for an identity; the update method synchronizes it from current SwiftUI state. A Coordinator translates target–action or delegate callbacks back into bindings and closures.

Define one source of truth at the boundary. SwiftUI owns layout for represented objects, so wrapper code should not fight it by assigning frames and transforms. Prevent feedback loops by comparing current values before mutating, clean up observers and delegates, and keep bridge types thin rather than hiding whole feature architectures inside them.

  • UIHostingController: UIKit controller that manages SwiftUI content.
  • UIViewRepresentable: SwiftUI wrapper for a UIView.
  • UIViewControllerRepresentable: SwiftUI wrapper for a controller.
  • Coordinator: reference object bridging callbacks.
  • Update method: synchronizes an existing wrapped object from current state.
02

Learning stage

Syntax & Examples

A search-field wrapper sends UIKit editing events into a SwiftUI binding without recreating the field.

SearchField.swiftswift
import SwiftUI
import UIKit

struct SearchField: UIViewRepresentable {
  @Binding var text: String

  func makeCoordinator() -> Coordinator { Coordinator(text: $text) }

  func makeUIView(context: Context) -> UISearchTextField {
    let field = UISearchTextField()
    field.placeholder = "Search lessons"
    field.addTarget(context.coordinator,
                    action: #selector(Coordinator.changed(_:)),
                    for: .editingChanged)
    return field
  }

  func updateUIView(_ field: UISearchTextField, context: Context) {
    if field.text != text { field.text = text }
  }

  final class Coordinator: NSObject {
    private var text: Binding<String>
    init(text: Binding<String>) { self.text = text }

    @objc func changed(_ sender: UISearchTextField) {
      text.wrappedValue = sender.text ?? ""
    }
  }
}
SwiftUI owns the value, UIKit emits edits, and updateUIView synchronizes only when necessary.
03

Learning stage

Real-World Usage

Connect the UIKit concept to complete, maintainable application features.

  • Push a new SwiftUI feature from an existing UIKit navigation stack.
  • Reuse a mature camera, map, or document controller in SwiftUI.
  • Host SwiftUI content inside a UIKit cell with platform configurations.
  • Migrate one product surface while preserving tested infrastructure.
04

Learning stage

Common Mistakes

Identify lifecycle, ownership, identity, layout, accessibility, and user-experience risks.

  • Keeping separate mutable truth in both frameworks.
  • Recreating the wrapped view during every update.
  • Setting a represented controller's frame against SwiftUI ownership.
  • Forgetting to remove observers or clear delegates.
  • Using a bridge where a native framework component already solves the need.
05

Learning stage

Practice Exercises

Build the behavior in a small Xcode project and inspect it across realistic states.

Activity 1

Host a SwiftUI detail

Push a UIHostingController containing a SwiftUI lesson detail from a UIKit course list and pass a completion action back.

Hint: Decide which side owns completion state before building the bridge.

Activity 2

Wrap a UIKit controller

Expose an image picker or document controller through UIViewControllerRepresentable and use a coordinator for its delegate.

Hint: Include cancellation and cleanup paths.

06

Learning stage

Knowledge Check

Answer each question before revealing the explanation.

QUESTION 1

What does UIHostingController provide?

  1. A.A UIKit view controller that manages a SwiftUI view hierarchy
  2. B.A database
  3. C.A collection snapshot
  4. D.An Auto Layout constraint
Reveal answer

A UIKit view controller that manages a SwiftUI view hierarchy

UIKit can navigate, present, or contain it like another controller.

QUESTION 2

What is the role of updateUIView or updateUIViewController?

Reveal answer

Synchronize the existing UIKit object with the latest SwiftUI state.

Creation happens in make; subsequent state changes flow through update.

07

Learning stage

Interview Preparation

Explain the design in terms of lifecycle, identity, ownership, system behavior, and trade-offs.

How would you migrate a UIKit app incrementally to SwiftUI?

Short answer: Use hosting controllers for new SwiftUI screens and representables only where SwiftUI needs existing UIKit components.

Explore the detailed answer

I choose feature boundaries, keep one source of truth, pass explicit inputs and events, and preserve existing navigation or services where useful. Coordinators bridge delegate callbacks. I test lifecycle, sizing, dismissal, and state synchronization at every boundary rather than creating a broad hidden dependency layer.

Possible follow-ups

  • • Who should own navigation during migration?
  • • How do you avoid update feedback loops?
08

Learning stage

Key Takeaways

UIKit–SwiftUI interoperability supports incremental architecture when boundaries define ownership, input synchronization, callback flow, layout, and cleanup.

  • Host SwiftUI in UIKit with UIHostingController.
  • Wrap UIKit for SwiftUI with representables.
  • Create once and update from state.
  • Use coordinators to bridge callbacks.
  • Keep one source of truth and respect layout ownership.