iOS集成Flutter自定义入口失败:引擎仍寻找main()
将Flutter集成到iOS应用中,此前通过flutterEngine.run()可正常加载main.dart页面。现在尝试调用flutterEngine.run(withEntrypoint: "screenAEntrypoint"),加载lib目录下screen_a.dart中标记@pragma('vm:entry-point')的全局函数screenAEntrypoint()以显示ScreenA页面,但Xcode控制台报错无法运行main Dart入口点、无法创建根隔离区。添加libraryURI: "screen_a.dart"参数后,又提示找不到该库。为何指定自定义入口点后,引擎仍会尝试寻找main()而非目标函数?
Swift侧FlutterEngine创建代码
import SwiftUI import Flutter import FlutterPluginRegistrant // Create a Flutter Engine class FlutterDependencies: ObservableObject { let flutterEngine = FlutterEngine(name: "my flutter engine"); init(){ // Runs the default Dart entrypoint with a default Flutter route. main.dart // flutterEngine.run(); //main.dart entry point flutterEngine.run(withEntrypoint: "screenAEntrypoint"); // flutterEngine.run(withEntrypoint: "screenAEntrypoint", libraryURI: "screen_a.dart"); // Connects plugins with iOS platform code to this app. GeneratedPluginRegistrant.register(with: self.flutterEngine); } } @main struct flutter_integration_testApp: App { // flutterDependencies will be injected using EnvironmentObject. @StateObject var flutterDependencies = FlutterDependencies() var body: some Scene { WindowGroup { ContentView().environmentObject(flutterDependencies) } } }
Swift侧ContentView代码
import SwiftUI import CoreData import Flutter struct ContentView: View { // Flutter dependencies are passed in an EnvironmentObject. @EnvironmentObject var flutterDependencies: FlutterDependencies // Button is created to call the showFlutter function when pressed. var body: some View { Text("iOS View") Button("Show Flutter!") { showFlutter() } } func showFlutter() { // Get the RootViewController. guard let windowScene = UIApplication.shared.connectedScenes .first(where: { $0.activationState == .foregroundActive && $0 is UIWindowScene }) as? UIWindowScene, let window = windowScene.windows.first(where: \.isKeyWindow), let rootViewController = window.rootViewController else { return } // Create the FlutterViewController. let flutterViewController = FlutterViewController( engine: flutterDependencies.flutterEngine, nibName: nil, bundle: nil) flutterViewController.modalPresentationStyle = .overCurrentContext flutterViewController.isViewOpaque = false rootViewController.present(flutterViewController, animated: true) } }
Dart侧screen_a.dart代码
import 'package:flutter/material.dart'; @pragma('vm:entry-point') void screenAEntrypoint() { runApp(const MaterialApp( home: ScreenA(), )); } // @pragma('vm:entry-point') class ScreenA extends StatelessWidget { const ScreenA({super.key}); @override Widget build(BuildContext context) { return Scaffold( appBar: AppBar( title: const Text("Screen A"), ), body: const Text("Screen A entry point"), ); } }
报错日志
调用flutterEngine.run(withEntrypoint: "screenAEntrypoint")时:
2023-10-03 13:59:59.509135+0200 flutter integration test[78506:757029] [VERBOSE-2:dart_isolate.cc(168)] Could not run the run main Dart entrypoint. 2023-10-03 13:59:59.510175+0200 flutter integration test[78506:757029] [VERBOSE-2:runtime_controller.cc(422)] Could not create root isolate. 2023-10-03 13:59:59.510244+0200 flutter integration test[78506:757029] [VERBOSE-2:shell.cc(614)] Could not launch engine with configuration.
添加libraryURI: "screen_a.dart"参数时:
2023-10-03 14:17:09.961063+0200 flutter integration test[81661:784695] [VERBOSE-2:shell.cc(91)] Dart Error: Dart_LookupLibrary: library 'screen_a.dart' not found. 2023-10-03 14:17:09.961165+0200 flutter integration test[81661:784695] [VERBOSE-2:dart_isolate.cc(667)] Could not resolve main entrypoint function. 2023-10-03 14:17:09.961228+0200 flutter integration test[81661:784695] [VERBOSE-2:dart_isolate.cc(168)] Could not run the run main Dart entrypoint. 2023-10-03 14:17:09.962495+0200 flutter integration test[81661:784695] [VERBOSE-2:runtime_controller.cc(422)] Could not create root isolate. 2023-10-03 14:17:09.962563+0200 flutter integration test[81661:784695] [VERBOSE-2:shell.cc(614)] Could not launch engine with configuration.
问题原因及解决办法
核心原因
- 未指定正确的库URI:
libraryURI参数需要传入Dart包的标准URI格式(package:<项目名>/文件名.dart),而非直接写本地文件名,否则Flutter引擎无法定位到目标库。 - 未指定库URI时的默认行为:当只传
entrypoint参数时,Flutter引擎默认在main.dart所在的根库中查找目标函数,而screenAEntrypoint不在该库内,引擎找不到后会 fallback 尝试调用默认的main()函数,最终因找不到可执行入口报错。
解决步骤
修正libraryURI参数
打开Flutter模块的pubspec.yaml,找到name字段(比如示例中的flutter_integration_test),将libraryURI修改为:flutterEngine.run(withEntrypoint: "screenAEntrypoint", libraryURI: "package:flutter_integration_test/screen_a.dart");注意替换
flutter_integration_test为你自己的Flutter项目名称。确保编译产物最新
执行以下命令清理并重新构建Flutter模块:flutter clean flutter pub get之后回到Xcode,执行
Product > Clean Build Folder,再重新编译iOS项目。验证入口点函数有效性
确认screenAEntrypoint是全局函数,且@pragma('vm:entry-point')标记正确(该标记用于防止Flutter编译优化时移除未被直接引用的函数),你的代码中这部分已经符合要求,无需修改。插件注册顺序(可选)
确保GeneratedPluginRegistrant.register(with: self.flutterEngine)在flutterEngine.run()之后调用,避免插件初始化时引擎未完全启动的问题。
内容的提问来源于stack exchange,提问作者Vincenzo

