Añadir una pantalla de Flutter a una aplicación macOS
Aprende cómo añadir una única pantalla de Flutter a tu aplicación macOS existente.
Esta guía describe cómo añadir una única pantalla de Flutter a una aplicación macOS existente.
Iniciar un FlutterEngine y un FlutterViewController
#Para lanzar una pantalla de Flutter desde una aplicación macOS existente,
inicias un FlutterEngine
y un FlutterViewController.
El FlutterEngine puede tener la misma vida útil
que tu FlutterViewController o sobrevivir a tu FlutterViewController.
Consulta Secuencia de carga y rendimiento para obtener más análisis sobre las compensaciones de latencia y memoria al preparar previamente un motor.
Crear un FlutterEngine
#El lugar donde crees un FlutterEngine depende de tu aplicación anfitriona.
En este ejemplo, creamos un objeto FlutterEngine dentro de un objeto
SwiftUI Observable
llamado FlutterDependencies.
Prepara previamente el motor llamando a run() y luego inyecta este objeto
en una ContentView usando el modificador de vista environment().
import SwiftUI
import FlutterMacOS
// The following library connects plugins with macOS platform code to this app.
import FlutterPluginRegistrant
@Observable
class FlutterDependencies {
let flutterEngine = FlutterEngine(name: "my flutter engine", project: nil)
init() {
// Runs the default Dart entrypoint with a default Flutter route.
flutterEngine.run(withEntrypoint: nil)
// Connects plugins with macOS platform code to this app.
RegisterGeneratedPlugins(registry: self.flutterEngine)
}
}
@main
struct MyApp: App {
// flutterDependencies will be injected through the view environment.
@State var flutterDependencies = FlutterDependencies()
var body: some Scene {
WindowGroup {
ContentView()
.environment(flutterDependencies)
}
}
}
Como ejemplo, demostramos la creación de un FlutterEngine,
expuesto como una propiedad, al inicio de la aplicación en el app delegate.
import Cocoa
import FlutterMacOS
// The following library connects plugins with macOS platform code to this app.
import FlutterPluginRegistrant
@main
class AppDelegate: FlutterAppDelegate {
lazy var flutterEngine = FlutterEngine(name: "my flutter engine", project: nil)
override func applicationDidFinishLaunching(_ aNotification: Notification) {
flutterEngine.run(withEntrypoint: nil)
RegisterGeneratedPlugins(registry: self.flutterEngine)
}
}
Mostrar un FlutterViewController con tu FlutterEngine
#El siguiente ejemplo muestra una ContentView genérica con un
NavigationLink
conectado a una pantalla de Flutter.
Primero, crea un FlutterViewControllerRepresentable
para representar el FlutterViewController.
El constructor de FlutterViewController toma
el FlutterEngine previamente preparado como argumento,
el cual se inyecta a través del entorno de la vista.
import SwiftUI
import FlutterMacOS
struct FlutterViewControllerRepresentable: NSViewControllerRepresentable {
// Flutter dependencies are passed in through the view environment.
@Environment(FlutterDependencies.self) var flutterDependencies
func makeNSViewController(context: Context) -> FlutterViewController {
return FlutterViewController(
engine: flutterDependencies.flutterEngine,
nibName: nil,
bundle: nil
)
}
func updateNSViewController(_ nsViewController: FlutterViewController, context: Context) {}
}
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink("My Flutter Feature") {
FlutterViewControllerRepresentable()
}
}
}
}
Ahora tienes una pantalla de Flutter embebida en tu aplicación macOS.
El siguiente ejemplo muestra un ViewController genérico con un
NSButton conectado para presentar un FlutterViewController.
El FlutterViewController utiliza la instancia de FlutterEngine
creada en el AppDelegate.
import Cocoa
import FlutterMacOS
class ViewController: NSViewController {
override func viewDidLoad() {
super.viewDidLoad()
// Make a button to call the showFlutter function when pressed.
let button = NSButton(title: "Show Flutter!", target: self, action: #selector(showFlutter))
button.frame = CGRect(x: 202, y: 187, width: 160.0, height: 40.0)
self.view.addSubview(button)
}
@objc func showFlutter() {
let flutterEngine = (NSApplication.shared.delegate as! AppDelegate).flutterEngine
let flutterViewController =
FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
self.addChild(flutterViewController)
flutterViewController.view.frame = self.view.bounds
presentAsModalWindow(flutterViewController)
}
}
Ahora tienes una pantalla de Flutter embebida en tu aplicación macOS.
Alternativa - Crear un FlutterViewController con un FlutterEngine implícito
#Como alternativa al ejemplo anterior,
puedes dejar que el FlutterViewController cree implícitamente
su propio FlutterEngine sin preparar uno con anticipación.
Por lo general, esto no se recomienda
porque crear un FlutterEngine bajo demanda podría introducir una latencia notable
entre el momento en que se presenta el FlutterViewController
y cuando renderiza su primer frame.
Sin embargo, esto podría ser útil si la pantalla de Flutter se muestra raras veces,
cuando no hay buenas heurísticas
para determinar cuándo debe iniciarse la Dart VM,
y cuando Flutter no necesita persistir el estado entre view controllers.
Para permitir que el FlutterViewController se presente sin un FlutterEngine existente,
omite la construcción de FlutterEngine,
y crea el FlutterViewController sin una referencia a un motor.
// Existing code omitted.
func makeNSViewController(context: Context) -> FlutterViewController {
return FlutterViewController()
}
// Existing code omitted.
func showFlutter() {
let flutterViewController = FlutterViewController()
self.addChild(flutterViewController)
flutterViewController.view.frame = self.view.bounds
presentAsModalWindow(flutterViewController)
}
Consulta Secuencia de carga y rendimiento para obtener más exploraciones sobre la latencia y el uso de memoria.
Usar el FlutterAppDelegate
#Se recomienda, aunque no es obligatorio, que la subclase UIApplicationDelegate
de tu aplicación herede de FlutterAppDelegate.
El FlutterAppDelegate realiza funciones tales como:
- Reenviar devoluciones de llamada de la aplicación como
openURLsa plugins como google_sign_in.
Crear una subclase de FlutterAppDelegate
#La creación de una subclase de FlutterAppDelegate en aplicaciones UIKit se mostró
en la sección Iniciar un FlutterEngine y un FlutterViewController.
En una aplicación SwiftUI, puedes crear una subclase de FlutterAppDelegate
y anotarla con la macro Observable()
de la siguiente manera:
import SwiftUI
import FlutterMacOS
@Observable
class AppDelegate: FlutterAppDelegate {
let flutterEngine = FlutterEngine(name: "my flutter engine", project: nil)
override func applicationDidFinishLaunching(_ aNotification: Notification) {
// Runs the default Dart entrypoint with a default Flutter route.
flutterEngine.run(withEntrypoint: nil)
// Used to connect plugins (only if you have plugins
// with macOS platform code).
RegisterGeneratedPlugins(registry: self.flutterEngine)
}
}
@main
struct MyApp: App {
// Use this property wrapper to tell SwiftUI
// it should use the AppDelegate class for the application delegate
@NSApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
var body: some Scene {
WindowGroup {
ContentView()
}
}
}
Luego, en tu vista, el AppDelegate es accesible
a través del entorno de la vista.
import SwiftUI
import FlutterMacOS
struct FlutterViewControllerRepresentable: NSViewControllerRepresentable {
// Access the AppDelegate through the view environment.
@Environment(AppDelegate.self) var appDelegate
func makeNSViewController(context: Context) -> FlutterViewController {
return FlutterViewController(
engine: appDelegate.flutterEngine,
nibName: nil,
bundle: nil
)
}
func updateNSViewController(_ nsViewController: FlutterViewController, context: Context) {}
}
struct ContentView: View {
var body: some View {
NavigationStack {
NavigationLink("My Flutter Feature") {
FlutterViewControllerRepresentable()
}
}
}
}
A menos que se indique lo contrario, la documentación de este sitio refleja Flutter 3.44.0. Página actualizada por última vez el 2026-05-18. Ver código fuente oreportar un problema.