Using Native iOS Widgets With Flutter Via SwiftUI Interop
Oct 31, 2025



Summary
Summary
Summary
Summary
This tutorial shows how to embed SwiftUI native widgets into a Flutter app. It covers creating a SwiftUI view, hosting it in a UIView via UIHostingController, implementing a FlutterPlatformViewFactory in iOS, registering it with the Flutter registrar, and instantiating the native view in Dart using UiKitView with creationParams and MethodChannel messaging. It also outlines lifecycle and performance best practices.
This tutorial shows how to embed SwiftUI native widgets into a Flutter app. It covers creating a SwiftUI view, hosting it in a UIView via UIHostingController, implementing a FlutterPlatformViewFactory in iOS, registering it with the Flutter registrar, and instantiating the native view in Dart using UiKitView with creationParams and MethodChannel messaging. It also outlines lifecycle and performance best practices.
This tutorial shows how to embed SwiftUI native widgets into a Flutter app. It covers creating a SwiftUI view, hosting it in a UIView via UIHostingController, implementing a FlutterPlatformViewFactory in iOS, registering it with the Flutter registrar, and instantiating the native view in Dart using UiKitView with creationParams and MethodChannel messaging. It also outlines lifecycle and performance best practices.
This tutorial shows how to embed SwiftUI native widgets into a Flutter app. It covers creating a SwiftUI view, hosting it in a UIView via UIHostingController, implementing a FlutterPlatformViewFactory in iOS, registering it with the Flutter registrar, and instantiating the native view in Dart using UiKitView with creationParams and MethodChannel messaging. It also outlines lifecycle and performance best practices.
Key insights:
Key insights:
Key insights:
Key insights:
Setup Your iOS Host App: Register a FlutterPlatformViewFactory in AppDelegate to expose native views to Flutter by a unique viewType string.
Build A SwiftUI View And Wrapper: Implement SwiftUI views to accept serializable props and host them in UIHostingController for UIView interoperability.
Register A Platform View Factory In iOS: Return a UIView from your factory's create(...) that holds the UIHostingController.view; decode creationParams for initial state.
Use The Native View In Flutter: Instantiate with UiKitView using the registered viewType and use MethodChannel for two-way messaging and events.
Performance And Lifecycle: Platform views are heavier—minimize count, keep initialization cheap, and properly clean up subscriptions to avoid leaks.
Introduction
Embedding native iOS UI into a Flutter app can be necessary when you need platform-specific widgets, animations, or system controls not available in Flutter. SwiftUI makes building native components concise; Flutter's Platform Views let you embed those native views. This tutorial shows a pragmatic path: create a SwiftUI view, host it in a UIView, register it with Flutter as a platform view factory on iOS, and instantiate it from Flutter using UiKitView. You will learn lifecycle, messaging, and best practices for smooth integration.
Setup Your iOS Host App
Open the iOS runner in Xcode (ios/Runner.xcworkspace). You will register a FlutterPlatformViewFactory from AppDelegate (or SceneDelegate) so Flutter can instantiate native views by type name. Add a new Swift file to your iOS runner target and import Flutter. Ensure your Podfile uses use_frameworks! or supports Swift interoperability and rebuild pods if necessary.
Key steps on the iOS side:
Create a class conforming to FlutterPlatformViewFactory.
Create the platform view by returning a UIView that hosts your SwiftUI view.
Register the factory with the FlutterPluginRegistrar using a unique viewType string.
A minimal Swift factory (conceptual) — implement in your iOS target:
import Flutter
import UIKit
import SwiftUI
class SwiftUIPlatformViewFactory: NSObject, FlutterPlatformViewFactory {
let messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) { self.messenger = messenger }
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return SwiftUIPlatformView(frame: frame, viewId: viewId, args: args, messenger: messenger)
}
}
class SwiftUIPlatformView: NSObject, FlutterPlatformView {
private let hostingView: UIView
init(frame: CGRect, viewId: Int64, args: Any?, messenger: FlutterBinaryMessenger) {
let mySwiftUIView = MySwiftUIView(props: args as? [String:Any] ?? [:])
let controller = UIHostingController(rootView: mySwiftUIView)
controller.view.backgroundColor = .clear
controller.view.frame = frame
hostingView = controller.view
super.init()
}
func view() -> UIView { hostingView }
}Register the factory in AppDelegate's didFinishLaunchingWithOptions:
let factory = SwiftUIPlatformViewFactory(messenger: registrar.messenger())
registrar.register(factory, withId: "com.example/swiftui_view")Build A SwiftUI View And Wrapper
Design your SwiftUI view to accept an input model and expose actions via closures or Combine publishers. Keep the view lightweight and avoid heavy Flutter-specific state in SwiftUI; instead send minimal inputs and expose callbacks for user actions.
Example SwiftUI signature:
struct MySwiftUIView: View {
var props: [String: Any]
var body: some View {
Text(props["title"] as? String ?? "Default")
.padding()
}
}If you need two-way messaging, use FlutterMethodChannel in your Swift platform view to send events, and listen on the Flutter side.
Register A Platform View Factory In iOS
Registration must happen before Flutter renders the Dart UI that requests the platform view. In most apps, AppDelegate is the right place. Use a unique view type string — the Dart UiKitView will reference it. For creation parameters, pass a JSON-serializable map from Flutter; receive and decode it as args in create(...).
Consider lifecycle details: UIHostingController manages SwiftUI state, but Flutter may embed and remove the view frequently (scrolling lists). Make your platform view stateless where possible and perform cleanup in deinit.
Use The Native View In Flutter
From Flutter, create an UiKitView referencing the viewType you registered. Provide creationParams for initial props and optionally use a MethodChannel for events.
A simple Dart usage example:
UiKitView(
viewType: 'com.example/swiftui_view',
creationParams: {'title': 'Hello from Flutter'},
creationParamsCodec: const StandardMessageCodec(),
onPlatformViewCreated: (id) {
// Optionally wire a MethodChannel for callbacks
},
)For callbacks from iOS use a MethodChannel named with the view id. Example pattern:
final channel = MethodChannel('com.example/swiftui_view_/$id');
channel.setMethodCallHandler((call) async { if (call.method == 'onTap') print(call.arguments); });UiKitView supports gestureMode and hitTestBehavior; if your SwiftUI view needs gestures, ensure you set gestureMode: PlatformViewGestureRecognizers if using gesture recognizers on the Flutter side.
Performance And Lifecycle Considerations
Platform views are heavier than pure Flutter widgets. Avoid embedding many platform views in long lists; prefer rasterizing snapshots if you need many identical native views. Keep the SwiftUI view initialization cheap, and reuse hosting controllers where possible. Always test memory and CPU profiles on real devices.
Use creationParams for immutable data and MethodChannels or EventChannels for dynamic updates. Manage teardown correctly — Flutter will call dispose on the platform view wrapper; ensure observers/subscriptions in SwiftUI are canceled to avoid leaks.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Embedding SwiftUI views in Flutter via iOS platform views gives access to native widgets and system UI without rewriting your whole UI in Swift. The workflow is: build a SwiftUI view, host it with UIHostingController inside a FlutterPlatformView, register a factory in the iOS app, and instantiate it from Dart with UiKitView. Balance functionality and performance: use native views for unique capabilities and keep as much UI as possible in Flutter for portability.
Introduction
Embedding native iOS UI into a Flutter app can be necessary when you need platform-specific widgets, animations, or system controls not available in Flutter. SwiftUI makes building native components concise; Flutter's Platform Views let you embed those native views. This tutorial shows a pragmatic path: create a SwiftUI view, host it in a UIView, register it with Flutter as a platform view factory on iOS, and instantiate it from Flutter using UiKitView. You will learn lifecycle, messaging, and best practices for smooth integration.
Setup Your iOS Host App
Open the iOS runner in Xcode (ios/Runner.xcworkspace). You will register a FlutterPlatformViewFactory from AppDelegate (or SceneDelegate) so Flutter can instantiate native views by type name. Add a new Swift file to your iOS runner target and import Flutter. Ensure your Podfile uses use_frameworks! or supports Swift interoperability and rebuild pods if necessary.
Key steps on the iOS side:
Create a class conforming to FlutterPlatformViewFactory.
Create the platform view by returning a UIView that hosts your SwiftUI view.
Register the factory with the FlutterPluginRegistrar using a unique viewType string.
A minimal Swift factory (conceptual) — implement in your iOS target:
import Flutter
import UIKit
import SwiftUI
class SwiftUIPlatformViewFactory: NSObject, FlutterPlatformViewFactory {
let messenger: FlutterBinaryMessenger
init(messenger: FlutterBinaryMessenger) { self.messenger = messenger }
func create(withFrame frame: CGRect, viewIdentifier viewId: Int64, arguments args: Any?) -> FlutterPlatformView {
return SwiftUIPlatformView(frame: frame, viewId: viewId, args: args, messenger: messenger)
}
}
class SwiftUIPlatformView: NSObject, FlutterPlatformView {
private let hostingView: UIView
init(frame: CGRect, viewId: Int64, args: Any?, messenger: FlutterBinaryMessenger) {
let mySwiftUIView = MySwiftUIView(props: args as? [String:Any] ?? [:])
let controller = UIHostingController(rootView: mySwiftUIView)
controller.view.backgroundColor = .clear
controller.view.frame = frame
hostingView = controller.view
super.init()
}
func view() -> UIView { hostingView }
}Register the factory in AppDelegate's didFinishLaunchingWithOptions:
let factory = SwiftUIPlatformViewFactory(messenger: registrar.messenger())
registrar.register(factory, withId: "com.example/swiftui_view")Build A SwiftUI View And Wrapper
Design your SwiftUI view to accept an input model and expose actions via closures or Combine publishers. Keep the view lightweight and avoid heavy Flutter-specific state in SwiftUI; instead send minimal inputs and expose callbacks for user actions.
Example SwiftUI signature:
struct MySwiftUIView: View {
var props: [String: Any]
var body: some View {
Text(props["title"] as? String ?? "Default")
.padding()
}
}If you need two-way messaging, use FlutterMethodChannel in your Swift platform view to send events, and listen on the Flutter side.
Register A Platform View Factory In iOS
Registration must happen before Flutter renders the Dart UI that requests the platform view. In most apps, AppDelegate is the right place. Use a unique view type string — the Dart UiKitView will reference it. For creation parameters, pass a JSON-serializable map from Flutter; receive and decode it as args in create(...).
Consider lifecycle details: UIHostingController manages SwiftUI state, but Flutter may embed and remove the view frequently (scrolling lists). Make your platform view stateless where possible and perform cleanup in deinit.
Use The Native View In Flutter
From Flutter, create an UiKitView referencing the viewType you registered. Provide creationParams for initial props and optionally use a MethodChannel for events.
A simple Dart usage example:
UiKitView(
viewType: 'com.example/swiftui_view',
creationParams: {'title': 'Hello from Flutter'},
creationParamsCodec: const StandardMessageCodec(),
onPlatformViewCreated: (id) {
// Optionally wire a MethodChannel for callbacks
},
)For callbacks from iOS use a MethodChannel named with the view id. Example pattern:
final channel = MethodChannel('com.example/swiftui_view_/$id');
channel.setMethodCallHandler((call) async { if (call.method == 'onTap') print(call.arguments); });UiKitView supports gestureMode and hitTestBehavior; if your SwiftUI view needs gestures, ensure you set gestureMode: PlatformViewGestureRecognizers if using gesture recognizers on the Flutter side.
Performance And Lifecycle Considerations
Platform views are heavier than pure Flutter widgets. Avoid embedding many platform views in long lists; prefer rasterizing snapshots if you need many identical native views. Keep the SwiftUI view initialization cheap, and reuse hosting controllers where possible. Always test memory and CPU profiles on real devices.
Use creationParams for immutable data and MethodChannels or EventChannels for dynamic updates. Manage teardown correctly — Flutter will call dispose on the platform view wrapper; ensure observers/subscriptions in SwiftUI are canceled to avoid leaks.
Vibe Studio

Vibe Studio, powered by Steve’s advanced AI agents, is a revolutionary no-code, conversational platform that empowers users to quickly and efficiently create full-stack Flutter applications integrated seamlessly with Firebase backend services. Ideal for solo founders, startups, and agile engineering teams, Vibe Studio allows users to visually manage and deploy Flutter apps, greatly accelerating the development process. The intuitive conversational interface simplifies complex development tasks, making app creation accessible even for non-coders.
Conclusion
Embedding SwiftUI views in Flutter via iOS platform views gives access to native widgets and system UI without rewriting your whole UI in Swift. The workflow is: build a SwiftUI view, host it with UIHostingController inside a FlutterPlatformView, register a factory in the iOS app, and instantiate it from Dart with UiKitView. Balance functionality and performance: use native views for unique capabilities and keep as much UI as possible in Flutter for portability.
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Build Flutter Apps Faster with Vibe Studio
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.
Vibe Studio is your AI-powered Flutter development companion. Skip boilerplate, build in real-time, and deploy without hassle. Start creating apps at lightning speed with zero setup.






















