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 THIS TESTS: 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.
A GOOD ANSWER COVERS: 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.
COMMON WRONG ANSWERS: 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.
LIKELY FOLLOW-UPS: 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.
ONE 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.
Read the original → developer.apple.com
Get five bites like this every day.
Tezvyn delivers a daily feed of 60-second tech bites with quizzes to lock in what you learn.