通常我們面對(duì)的需求不是直接用flutter開發(fā)一個(gè)新app,而是希望在已有的項(xiàng)目中嵌入flutter,開發(fā)部分頁(yè)面,根據(jù)開發(fā)情況逐漸進(jìn)行過度.下面介紹一下iOS端如何與Flutter進(jìn)行混編.
1.工程目錄結(jié)構(gòu)
因?yàn)槭强缙脚_(tái)開發(fā),通常有三個(gè)工程:iOS,安卓,flutter.由于本人是iOS開發(fā),所以這里只列舉iOS.目錄結(jié)構(gòu)如下:
-Flutter_iOS_App
-flutter_app
官方建議我們能將三個(gè)項(xiàng)目都放在同級(jí)目錄中,另外flutter目前不能很好的支持bitcode,所以iOS工程中需要關(guān)閉.
2.創(chuàng)建flutter模塊
在創(chuàng)建iOS項(xiàng)目后,需要?jiǎng)?chuàng)建對(duì)應(yīng)的flutter模塊.
進(jìn)入到和iOS項(xiàng)目同級(jí)目錄后,運(yùn)行命令:
flutter create -t module flutter_app
// 這里有個(gè)注意點(diǎn),官方對(duì)于flutter包命名要求是必須小寫,并且單詞間用 _ 隔開.不然很可能創(chuàng)建失敗.
3.配置iOS項(xiàng)目的config文件
總共有如下三個(gè)文件:
-Flutter.xcconfig:指向flutter內(nèi)部的Generated.xcconfig文件,主要是一些基礎(chǔ)配置
-Debug.xcconfig:Debug環(huán)境配置文件
-Release.xcconfig:Release環(huán)境配置文件
Flutter.xcconfig文件內(nèi)容:
// xxxxxxx用flutter的項(xiàng)目名稱代替
#include "../xxxxxxx/.ios/Flutter/Generated.xcconfig"
Debug.xcconfig文件內(nèi)容:
#include "Flutter.xcconfig"
// 如果使用了Cocoapods难捌,那么需要引入 cocoapods 的config文件,xxxxxxx用iOS工程名代替
#include "Pods/Target Support Files/Pods-xxxxxxx/Pods-xxxxxxx.debug.xcconfig"
Release.xcconfig文件內(nèi)容:
#include "Flutter.xcconfig"
// 如果使用了Cocoapods垢夹,那么需要引入 cocoapods 的config文件,xxxxxxx用iOS工程名代替
#include "Pods/Target Support Files/Pods-xxxxxxx/Pods-xxxxxxx.release.xcconfig"
4.配置config到iOS工程中
如圖:
5.設(shè)置flutter腳本
在iOS工程內(nèi)的target中,找到Build Phases 添加flutter執(zhí)行腳本,會(huì)生成一個(gè)engine文件夾和app.framework
:
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
這段腳本最好放在系統(tǒng)腳本的后面,運(yùn)行完這段腳本后我們發(fā)現(xiàn)生成的兩個(gè)framework在flutter項(xiàng)目?jī)?nèi),所以這時(shí)候需要修改一下xcode_backend.sh
腳本,讓它們?cè)趇OS工程內(nèi).
找到腳本,注釋掉如下代碼:
local derived_dir="${SOURCE_ROOT}/Flutter"
# if [[ -e "${project_path}/.ios" ]]; then
# derived_dir="${project_path}/.ios/Flutter"
# fi
RunCommand mkdir -p -- "$derived_dir"
AssertExists "$derived_dir"
6.將生成的文件和framework拖入工程內(nèi),
將App.framework 和Flutter.framework添加到Embedded Binaries中.
7.改造Appledegate文件
如下代碼:
// .h
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate,FlutterAppLifeCycleProvider>
// .m
@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];;
}
// 如果有用到其他生命周期方法,按照上面的示例替換就行了
@end
8.本地跳轉(zhuǎn)進(jìn)入flutter頁(yè)面
- (IBAction)push:(id)sender {
FlutterViewController *vc = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
vc.navigationItem.title = @"first flutter app";
[self.navigationController pushViewController:vc animated:YES];
}
此時(shí)用vscode打開flutter工程,然后終端cd到flutter工程內(nèi),執(zhí)行:
flutter attach // 等待Xcode運(yùn)行
運(yùn)行xcode,成功后點(diǎn)擊button,跳轉(zhuǎn)進(jìn)入flutter界面.
此時(shí)進(jìn)入flutter項(xiàng)目,修改main.dart
的title,然后在終端內(nèi)鍵盤點(diǎn)擊”r”,即可hot reload成功,title已經(jīng)被成功修改.
好了,到此基本能明白混編是怎么一會(huì)兒事兒了,下一篇將要介紹,iOS和Flutter的交互過程.