How it works
UIViewRepresentable is the bridge that lets a UIKit view live inside a SwiftUI layout. When SwiftUI doesn't offer a native equivalent for some control or platform view, you conform a type to UIViewRepresentable and SwiftUI treats the wrapped UIView as a first-class view it can size, position, and update. Reach for it whenever you need to embed UIKit-only functionality and have it participate in the SwiftUI view hierarchy and update cycle.
Conform a view type to UIViewRepresentable
The protocol is what turns an ordinary struct into a SwiftUI view backed by UIKit. Declaring
struct SpinnerView: UIViewRepresentablegives the type abody-free conformance toView, so it can be used anywhere a SwiftUI view is expected — hereSpinnerView()sits directly in the layout.Create the UIKit view in makeUIView(context:)
SwiftUI calls
makeUIView(context:)once to build the underlying view, and its return type fixes the associatedUIViewTypefor the conformance. In the example it returns aUIActivityIndicatorView, configured up front withUIActivityIndicatorView(style: .large),view.startAnimating(), andview.color = .systemBluebefore handing the instance back to SwiftUI.Reflect state changes in updateUIView(_:context:)
Whenever the relevant SwiftUI state changes, SwiftUI calls
updateUIView(_:context:)with the existing view so you can push the new values onto it. The spinner has no driving state, soupdateUIView(_ uiView: UIActivityIndicatorView, context: Context)is left empty — but this is the hook where bound data would flow into the UIKit view.Read the environment through Context
Both methods receive a
Contextcarrying the current SwiftUI environment, transaction, and (when declared) coordinator. Even unused, thecontextparameter is the channel through which SwiftUI-managed values reach your UIKit code during creation and every update.Apply SwiftUI modifiers to the wrapped view
Because the conformance makes the type a real SwiftUI view, standard modifiers apply to it like any other. The
.frame(width: 80, height: 80)attached toSpinnerView()constrains the embeddedUIActivityIndicatorViewwithin the surroundingVStack, showing the UIKit view honoring SwiftUI's layout system.
UIActivityIndicatorView(style: .large) to .medium and watch the wrapped UIKit spinner shrink inside its SwiftUI frame.Example & preview
Press Run live & edit to compile it in your browser — then edit the Swift on the left and the preview re-renders live.
struct UIViewRepresentableDemo: View {
struct SpinnerView: UIViewRepresentable {
func makeUIView(context: Context) -> UIActivityIndicatorView {
let view = UIActivityIndicatorView(style: .large)
view.startAnimating()
view.color = .systemBlue
return view
}
func updateUIView(_ uiView: UIActivityIndicatorView, context: Context) {}
}
var body: some View {
VStack(spacing: 16) {
Text("Wrapped UIKit View")
.font(.headline)
SpinnerView()
.frame(width: 80, height: 80)
Text("UIActivityIndicatorView")
.font(.caption)
.foregroundStyle(.secondary)
}
.padding()
}
}