Skip to content
tezvyn:

Integrate SwiftUI into UIKit and wrap UIKit for SwiftUI

Source: developer.apple.comMediumHow cards are made

Integrate SwiftUI into UIKit and wrap UIKit for SwiftUI

Tests bridging architecture between UIKit and SwiftUI using UIHostingController and UIViewRepresentable. A strong answer names hosting controllers for SwiftUI in UIKit, representable protocols for UIKit in SwiftUI, and lifecycle hooks.

What's really being asked

This question probes whether you understand the architectural boundary between UIKit and SwiftUI. Interviewer wants to know if you can move between declarative and imperative UI frameworks without breaking lifecycle contracts, state flow, or memory management. Senior candidates should demonstrate knowledge of the adapter types Apple provides and why they exist.

The full answer

First, for SwiftUI inside UIKit, use UIHostingController. You instantiate it with a SwiftUI view and add it as a child view controller, not just a subview. This ensures the SwiftUI lifecycle events, environment, and state work correctly. You must call addChild and didMove(toParent:) and constrain its view with Auto Layout or frames. Second, for UIKit inside SwiftUI, use UIViewRepresentable. Implement makeUIView to create the view and updateUIView to sync state changes. For delegate-based UIKit views like MKMapView, provide a Coordinator object via makeCoordinator to handle callbacks and avoid retain cycles. Third, mention sizing and layout. UIHostingController needs explicit constraints or preferredContentSize, while UIViewRepresentable should communicate intrinsic content size or use frame modifiers. Fourth, mention state ownership. SwiftUI state drives updateUIView, but UIKit events should update that state through bindings or closures to keep the source of truth in SwiftUI.

The mistakes people make

A major red flag is suggesting you can add a SwiftUI view directly to a UIKit view hierarchy without UIHostingController. This breaks environment, state, and lifecycle. Another red flag is trying to force UIKit views into SwiftUI by taking snapshots or using UIApplication.shared.windows. Some candidates forget makeCoordinator and try to make the representable struct itself the delegate, which causes mutability and lifecycle issues. Ignoring memory cleanup in updateUIView, such as repeatedly adding subviews instead of updating the existing one, also signals inexperience.

What usually comes next

How do you communicate from the UIKit view back to SwiftUI? Expect to discuss Binding, closures, or ObservableObject passed through the Coordinator. How do you handle view controllers instead of views? Mention UIViewControllerRepresentable. What performance considerations exist? Talk about avoiding redundant updates in updateUIView and diffing state efficiently. How do you push a UIKit navigation stack from SwiftUI or vice versa? This leads to UINavigationController bridging or using NavigationStack with UIKit-hosted islands.

A concrete example

Suppose you need to embed an MKMapView in a SwiftUI screen. You create a struct MapView: UIViewRepresentable that holds a Binding<MKCoordinateRegion>. In makeUIView, you return an MKMapView. In updateUIView, you set the region if it changed. You define a Coordinator that conforms to MKMapViewDelegate and implements mapView(_:regionDidChangeAnimated:), which writes the new region back to the binding. You instantiate the coordinator in makeCoordinator and assign it as the map view delegate in makeUIView. This pattern keeps SwiftUI as the source of truth while letting UIKit handle rendering and gestures.

Interview question

When wrapping a delegate-based UIKit view for use in SwiftUI, what is the correct way to handle callbacks and avoid retain cycles?

  • a.Provide a Coordinator object via makeCoordinator and use it as the delegateCorrect
  • b.Conform the UIViewRepresentable struct to the delegate protocol and assign self as the delegate
  • c.Reassign the delegate inside updateUIView whenever the SwiftUI state changes
  • d.Wrap the UIKit view in a UIHostingController before adding it to the SwiftUI hierarchy
Why?

A Coordinator provides a stable reference to handle delegate callbacks without retain cycles. Making the representable struct the delegate is wrong because structs cannot reliably act as reference-type delegates and it introduces mutability and lifecycle issues.

Just read this? Test yourself on what you have been reading.

Read the original → developer.apple.com

You just looked this up. Could you explain it out loud?

That is the part interviews actually test. Tezvyn takes questions like this one and gives you what the interviewer is really checking, the answer that lands, and the mistake that ends the conversation, in the four minutes before your next meeting.

The iPhone app is on the way

We are building it. Until it lands, nothing here is held back from you: every interview card, your saved cards, streaks and the job board all work in Safari, plus hundreds of free practice quizzes of thirty questions each. Sign in and it all carries over to the app the day it arrives.

Want it as an icon? Tap Share at the bottom of Safari, then Add to Home Screen. It opens full screen and the cards you have read stay available offline.

Get it on Google PlayiPhone app coming soon

We are hiring for this. Open roles that interview on ios — each one lists the topics its interview covers.

See open roles