現有iOS工程引入Flutter
Flutter 是一個很有潛力的框架,但是目前使用Flutter的APP並不算很多,相關資料並不豐富,介紹現有工程引入Flutter的相關文章也比較少。專案從零開始,引入Flutter操作比較簡單,但是現有工程引入Flutter 需要費很多精力和時間,這裡是我在完成現有iOS工程引入Flutter後寫的一次總結文章。
Flutter 環境搭建
首先是要搭建Flutter環境,之前也寫了一篇相關文章 ofollow,noindex">搭建Flutter-iOS開發環境 ,可以參考一下 可以去官網檢視: github.com/flutter/flu… 比較簡單,這裡不做贅述。
現有iOS工程引入Flutter
一、建立Flutter module
首先建立flutter module,主要是用於獲取改flutter app中的Generated.xcconfig和framework
cd some/path/ $ flutter create -t module my_flutter 複製程式碼
也可以用
flutter create app 複製程式碼
建立flutter app,flutter app中也有Generated.xcconfig和framework
二、新建配置檔案
根據官網,需要在工程中建立三個配置檔案: Flutter.xcconfig
、 Debug.xcconfig
、 Release.xcconfig
在XCode工程對應目錄,右擊,選擇新建檔案(New File),選中建立xcconfig檔案,如圖:

在 Flutter.xcconfig
中填寫:
//這裡填寫前面建立的flutter module 的Generated.xcconfig的路徑 #include "../../my_flutter/.ios/Flutter/Generated.xcconfig" ENABLE_BITCODE=NO 複製程式碼
在 Debug.xcconfig
中填寫:
#include "../Flutter/Flutter.xcconfig" 複製程式碼
在 Release.xcconfig
中填寫:
#include "../Flutter/Flutter.xcconfig" FLUTTER_BUILD_MODE=release 複製程式碼
如果工程中用cocoapods管理,需要在 Debug.xcconfig
和 Release.xcconfig
新增pod的路徑:
例如 Release.xcconfig
中
#include "Flutter.xcconfig" #include "工程路徑/Pods/Target Support Files/******.release.xcconfig"//pod路徑 FLUTTER_BUILD_MODE=release 複製程式碼
在準備好這些xcconfig檔案後,需要到XCode工程PROJECT(注意是PROJECT,不是Target)中的Configuration選項裡,將對應的target選擇成前面的xcconfig檔案,Debug用Debug.xcconfig, Release用 Release.xcconfig ######注意:進行Archive打包的時候,無論是Debug包還是Release包,需要切換到Release.xcconfig,不然會報錯。

三、為編譯Dart引入相關build phase
在工程的Build Phase中新建一個 Run Script
,用於編譯時執行指令碼, 建立方法如圖:

建立 Run Script
後,需要移動其對應的位置,需要在 Target dependencies
之後,如果用cocoapods管理工程需要在, Check Pods Manifest.lock
之後:

在指令碼框中,填入以下程式碼,用於引進Flutter中的xcode_backend指令碼:
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build 複製程式碼
如圖:

四、生成和新增Framework
完成前面的配置後,便可以在XCode對工程進行編譯build (Command+B),在提示“ Build Success ” 後,在iOS工程資料夾中會生成一個Flutter資料夾,將其加入工程目錄中,建議和剛才xcconfig所在目錄並列,
右鍵專案目錄 ,選擇 Add Files to 'xxx' ,Options選 Create groups
,新增編譯生成的Flutter資料夾。需要注意但是:Flutter目錄下有個 flutter_assets
檔案,不能使用 Create groups
的方式新增,只能用 Creat folder references
的Options, 否則Flutter頁面會空白渲染不出來。可以刪了flutter_assets在用 Creat folder reference
s重新新增。
在新增完Flutter 資料夾之後,去 Embeded Binaries
中新增 App.framework
和 Flutter.framework

五、AppDelegate改造
Flutter需要和APP進行互動,需要對AppDelegate 進行改造:
AppDelegate.h檔案中:
#import <Flutter/Flutter.h> @interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate, FlutterAppLifeCycleProvider> @end 複製程式碼
AppDelegate.m 檔案中:
#import "AppDelegate.h" @interface AppDelegate () @end @implementation AppDelegate { FlutterPluginAppLifeCycleDelegate *_lifeCycleDelegate; } - (instancetype)init { if (self = [super init]) { _lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init]; } return self; } - (BOOL)application:(UIApplication*)application didFinishLaunchingWithOptions:(NSDictionary*)launchOptions { return [_lifeCycleDelegate application:application didFinishLaunchingWithOptions:launchOptions]; } - (void)applicationDidEnterBackground:(UIApplication*)application { [_lifeCycleDelegate applicationDidEnterBackground:application]; } - (void)applicationWillEnterForeground:(UIApplication*)application { [_lifeCycleDelegate applicationWillEnterForeground:application]; } - (void)applicationWillResignActive:(UIApplication*)application { [_lifeCycleDelegate applicationWillResignActive:application]; } - (void)applicationDidBecomeActive:(UIApplication*)application { [_lifeCycleDelegate applicationDidBecomeActive:application]; } - (void)applicationWillTerminate:(UIApplication*)application { [_lifeCycleDelegate applicationWillTerminate:application]; } - (void)application:(UIApplication*)application didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings { [_lifeCycleDelegate application:application didRegisterUserNotificationSettings:notificationSettings]; } - (void)application:(UIApplication*)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken { [_lifeCycleDelegate application:application didRegisterForRemoteNotificationsWithDeviceToken:deviceToken]; } - (void)application:(UIApplication*)application didReceiveRemoteNotification:(NSDictionary*)userInfo fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { [_lifeCycleDelegate application:application didReceiveRemoteNotification:userInfo fetchCompletionHandler:completionHandler]; } - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options { return [_lifeCycleDelegate application:application openURL:url options:options]; } - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url { return [_lifeCycleDelegate application:application handleOpenURL:url]; } - (BOOL)application:(UIApplication*)application openURL:(NSURL*)url sourceApplication:(NSString*)sourceApplication annotation:(id)annotation { return [_lifeCycleDelegate application:application openURL:url sourceApplication:sourceApplication annotation:annotation]; } - (void)application:(UIApplication*)application performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem completionHandler:(void (^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0) { [_lifeCycleDelegate application:application performActionForShortcutItem:shortcutItem completionHandler:completionHandler]; } - (void)application:(UIApplication*)application handleEventsForBackgroundURLSession:(nonnull NSString*)identifier completionHandler:(nonnull void (^)(void))completionHandler { [_lifeCycleDelegate application:application handleEventsForBackgroundURLSession:identifier completionHandler:completionHandler]; } - (void)application:(UIApplication*)application performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler { [_lifeCycleDelegate application:application performFetchWithCompletionHandler:completionHandler]; } - (void)addApplicationLifeCycleDelegate:(NSObject<FlutterPlugin>*)delegate { [_lifeCycleDelegate addDelegate:delegate]; } 複製程式碼
六、新建FlutterViewController
主要配置基本上已經完成,只要在 main.dart
實現Flutter的業務程式碼即可

main.dart
實現的Flutter頁面,如:
self.flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil]; [self.navigationController pushViewController:self.flutterViewController animated:YES]; 複製程式碼
後語
到這裡現有iOS工程引入Flutter的工作就完成了,一些細節上的修改需要根據場景進行修改,例如Flutter和Native的資料通訊等。