iOS - Flutter混合開發(fā)項目集成Flutter模塊詳細(xì)指南

前言

前一篇文章講解了Android原生工程如何集成Flutter項目的具體過程悦污,Flutter混合開發(fā)(一):Android項目集成Flutter模塊詳細(xì)指南 ,本篇將帶著大家來一起學(xué)習(xí)原生iOS項目如何集成Flutter切端。

因為每個版本的集成邏輯都是有差別的踏枣,所以這里交代下本篇文章的集成版本:

Flutter (channel dev钙蒙,v1.10.16)
dart (v2.7.0)
Xcode (v11.2)
cocoapds (1.8.4)

創(chuàng)建Flutter module

假如iOS項目的路徑是這樣的:flutter/flutter_hybrid/iOS Project,那么我們需要在iOS Project上一層目錄flutter_hybrid中創(chuàng)建Flutter module躬厌。

cd flutter/flutter_hybrid/

flutter create -t module flutter_module

輸入后控制臺打印如下:

$ flutter create -t module flutter_module
Creating project flutter_module...
  flutter_module/test/widget_test.dart (created)
  flutter_module/flutter_module.iml (created)
  flutter_module/.gitignore (created)
  flutter_module/.metadata (created)
  flutter_module/pubspec.yaml (created)
  flutter_module/README.md (created)
  flutter_module/lib/main.dart (created)
  flutter_module/flutter_module_android.iml (created)
  flutter_module/.idea/libraries/Flutter_for_Android.xml (created)
  flutter_module/.idea/libraries/Dart_SDK.xml (created)
  flutter_module/.idea/modules.xml (created)
  flutter_module/.idea/workspace.xml (created)
Running "flutter pub get" in flutter_module...                      1.2s
Wrote 12 files.

All done!
Your module code is in flutter_module/lib/main.dart.

看到All done就表示我們項目創(chuàng)建好了扛施。整個module目錄和原生Flutter基本一樣,主要就是Android匙奴、iOS的宿主工程和lib目錄以及pubspec.yaml文件泼菌。

添加Flutter module依賴

為iOS項目添加依賴需要使用CocoaPods,如果你還沒有用到CocoaPods哗伯,可以參考https://cocoapods.org/上面的說明來安裝CocoaPods篷角。

如果你的項目之前沒有使用過cocoapods,那么需要進(jìn)行初始化生成podfile文件伴澄,進(jìn)入iOS項目的根目錄執(zhí)行:

pod init

然后打開podfile文件非凌,進(jìn)行配置:

# 配置
flutter_application_path = '../flutter_module/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'iOSFlutterHybrid' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for iOSFlutterHybrid
  # 配置
  install_all_flutter_pods(flutter_application_path)

  target 'iOSFlutterHybridTests' do
    inherit! :search_paths
    # Pods for testing
  end

  target 'iOSFlutterHybridUITests' do
    # Pods for testing
  end

配置添加好后在項目根目錄運(yùn)行以下命令進(jìn)行安裝:

pod install

控制臺輸出:

Analyzing dependencies
Downloading dependencies
Installing Flutter (1.0.0)
Installing FlutterPluginRegistrant (0.0.1)
Installing flutter_module (0.0.1)
Generating Pods project
Integrating client project

[!] Please close any current Xcode sessions and use `iOSFlutterHybrid.xcworkspace` for this project from now on.
Pod installation complete! There are 3 dependencies from the Podfile and 3 total pods installed.

[!] Automatically assigning platform `iOS` with version `13.2` on target `iOSFlutterHybrid` because no platform was specified. Please specify a platform for this target in your Podfile. See `https://guides.cocoapods.org/syntax/podfile.html#platform`.

這里我們看到有三個依賴安裝完成了敞嗡。并提醒我們關(guān)閉當(dāng)前項目,在根目錄下面使用iOSFlutterHybrid.xcworkspace來打開運(yùn)行項目棱貌。這里可能很多人在執(zhí)行命令的時候會發(fā)現(xiàn)提示0個依賴完成婚脱。這里有可能是你的Xcode版本的問題勺像。因為Flutter要求最低版本是10.2及以上。

當(dāng)在flutter_module/pubspec.yaml中添加一個Flutter插件時篮洁,需要在flutter_module目錄下運(yùn)行:

flutter packages get

來刷新podhelper.rb腳本中的插件列表袁波,然后在iOS目錄下運(yùn)行:

pod install

這樣podhelper.rb腳本才能確保添加的插件和Flutter.framework能夠添加到iOS項目中蜗侈。

目前Flutter還不支持Bitcode,所以集成了Flutter的iOS項目需要禁用Bitcode。

在以下路徑下找到Bitcode并禁用:

Build Settings->Build Options->Enable Bitcode
image

flutter以前的版本是需要添加build phase以構(gòu)建Dart代碼叫倍,但是最新的版本已經(jīng)不需要添加了吆倦,可以自動構(gòu)建蚕泽。

調(diào)用Flutter module

Flutter為我們提供了兩種調(diào)用方式:FlutterViewController和FlutterEngine桥嗤,F(xiàn)lutterEngine在使用的時候會有一些問題,將在下文進(jìn)行說明荒吏。

FlutterViewController方式:

我們打開ViewController.m文件渊鞋,在里面添加一個加載flutter頁面的方法并且添加一個按鈕看來調(diào)用:

#import "ViewController.h"
#import <Flutter/Flutter.h>
#import "AppDelegate.h"

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
    [button addTarget:self action:@selector(handleButtonAction) forControlEvents:UIControlEventTouchUpInside];

    [button setTitle:@"加載Flutter" forState:UIControlStateNormal];
    [button setBackgroundColor:[UIColor blueColor]];
    button.frame = CGRectMake(100, 100, 160, 60);
    [self.view addSubview:button];
}

- (void)handleButtonAction{

    FlutterViewController *flutterViewController =[FlutterViewController new];
    //設(shè)置路由參數(shù)
    [flutterViewController setInitialRoute:@"route2"];
    [self presentViewController:flutterViewController animated:false completion:nil];

}

@end

當(dāng)我們運(yùn)行項目點擊加載Flutetr按鈕時,將會調(diào)用Flutter頁面特恬。和Android項目集成一樣,這里的setInitialRoute可以設(shè)置一個json數(shù)組來傳遞需要交互的參數(shù)癌刽。并在Flutter中使用window.defaultRouteName來獲取傳遞的參數(shù)妒穴。

FlutterEngine方式:

我們需要在AppDelegate中對FlutterEngine進(jìn)行初始化。打開AppDelegate.h文件:

#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end

在打開AppDelegate.m文件:

// 如果你需要用到Flutter插件時
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> 
#include "AppDelegate.h"

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application
    didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
  [self.flutterEngine runWithEntrypoint:nil];
  [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine]; //如果你需要用到Flutter插件時
  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end

然后在ViewController.m文件定義的handleButtonAction中調(diào)用:

- (void)handleButtonAction{

    FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine];
    FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
    [flutterViewController setInitialRoute:@"route2"];
    [self presentViewController:flutterViewController animated:false completion:nil];

}

當(dāng)我們運(yùn)行項目點擊加載Flutter按鈕時,將會調(diào)用Flutter頁面呢簸。前文講到使用FlutterEngine會有問題根时,就是我們setInitialRoute傳遞的參數(shù)在flutter中永遠(yuǎn)獲取到的都是 “/” ,這個是Fltter SDK的一個Bug确虱,所以如果必須依賴setInitialRoute替裆,還是使用FlutterViewController的形式來加載Flutter模塊辆童。

熱重啟/重新加載

大家在寫純Flutter應(yīng)用的時候,知道是有熱重啟/重新加載功能的故黑,但是在做混合開發(fā)的過程中庭砍,你會發(fā)現(xiàn)熱重啟/重新加載功能失效了场晶。那么如何在混合開發(fā)中開啟熱重啟/重新加載功能呢?

  • 首先接入我們的設(shè)備或者模擬器
  • 將我們的App關(guān)閉怠缸,退出后臺峰搪,在terminal中運(yùn)行 flutter attach命令
$ flutter attach
Waiting for a connection from Flutter on Android SDK built for x86...

復(fù)制代碼此時就在等待設(shè)備的連接。這里要注意的是凯旭,如果電腦連接了多臺設(shè)備需要使用 -d 命令來指定一臺設(shè)備概耻,參數(shù)為設(shè)備的id使套。

flutter attach -d '你的設(shè)備id'

然后啟動我們的應(yīng)用會看到控制臺輸出:

Done.
Syncing files to device Android SDK built for x86...             1,393ms

??  To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".
An Observatory debugger and profiler on Android SDK built for x86 is available at: http://127.0.0.1:59354/zRsDBfpesrk=/
For a more detailed help message, press "h". To detach, press "d"; to quit, press "q".

這樣就表示我們連接成功了。在輸出的日志中也告訴了我們?nèi)绾问褂脽嶂貑?重新加載功能鞠柄。

在Terminal中輸入以下命令?:?

r : 熱加載侦高;
R : 熱重啟;
h : 獲取幫助厌杜;
d : 斷開連接奉呛;
q : 退出瞧壮;

這里的的 d 和 q 的命令都有退出調(diào)試,區(qū)別在于 d 命令只是單純的斷開而 q 命令會將應(yīng)用退到后臺秦忿。

調(diào)試Dart代碼

同樣在混合開發(fā)過程中我們?nèi)绾握{(diào)試dart代碼呢?

  • 關(guān)閉我們的應(yīng)用
  • 點擊Android Studio工具欄上的Flutter Attach按鈕(需要安裝Flutter與Dart插件)
image
  • 啟動我們的應(yīng)用

接下來就可以像調(diào)試普通Flutter項目一樣來調(diào)試混合開發(fā)模式下的Dart代碼了。

總結(jié)

本文主要是講解了iOS集成Flutter項目的步驟辜窑,其中也遇到了一些問題切距,由于我的Xcode版本較低话肖,在集成的過程中iOS項目的依賴一直失敗。最后才發(fā)現(xiàn)是Xcode的版本問題床蜘。

如果你覺得文章還不錯扬蕊,請大家點贊分享下,你的肯定是對我最大的鼓勵和支持再愈。

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末府适,一起剝皮案震驚了整個濱河市,隨后出現(xiàn)的幾起案子疟暖,更是在濱河造成了極大的恐慌,老刑警劉巖欣舵,帶你破解...
    沈念sama閱讀 219,490評論 6 508
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件袜蚕,死亡現(xiàn)場離奇詭異遣疯,居然都是意外死亡数苫,警方通過查閱死者的電腦和手機(jī),發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 93,581評論 3 395
  • 文/潘曉璐 我一進(jìn)店門亡鼠,熙熙樓的掌柜王于貴愁眉苦臉地迎上來仁热,“玉大人,你說我怎么就攤上這事迅矛⊥担” “怎么了蚂踊?”我有些...
    開封第一講書人閱讀 165,830評論 0 356
  • 文/不壞的土叔 我叫張陵特纤,是天一觀的道長粪躬。 經(jīng)常有香客問我,道長吗货,這世上最難降的妖魔是什么拓哺? 我笑而不...
    開封第一講書人閱讀 58,957評論 1 295
  • 正文 為了忘掉前任,我火速辦了婚禮讼积,結(jié)果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好波岛,可當(dāng)我...
    茶點故事閱讀 67,974評論 6 393
  • 文/花漫 我一把揭開白布彻桃。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上,一...
    開封第一講書人閱讀 51,754評論 1 307
  • 那天惋戏,我揣著相機(jī)與錄音棕孙,去河邊找鬼。 笑死,一個胖子當(dāng)著我的面吹牛,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播凭涂,決...
    沈念sama閱讀 40,464評論 3 420
  • 文/蒼蘭香墨 我猛地睜開眼绢片,長吁一口氣:“原來是場噩夢啊……” “哼熙涤!你這毒婦竟也來了悼沿?” 一聲冷哼從身側(cè)響起义郑,我...
    開封第一講書人閱讀 39,357評論 0 276
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎纵顾,沒想到半個月后,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 45,847評論 1 317
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 37,995評論 3 338
  • 正文 我和宋清朗相戀三年缝呕,在試婚紗的時候發(fā)現(xiàn)自己被綠了话侧。 大學(xué)時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片新博。...
    茶點故事閱讀 40,137評論 1 351
  • 序言:一個原本活蹦亂跳的男人離奇死亡写隶,死狀恐怖鄙陡,靈堂內(nèi)的尸體忽然破棺而出毫捣,到底是詐尸還是另有隱情胡本,我是刑警寧澤披粟,帶...
    沈念sama閱讀 35,819評論 5 346
  • 正文 年R本政府宣布思灌,位于F島的核電站耗跛,受9級特大地震影響烟阐,放射性物質(zhì)發(fā)生泄漏。R本人自食惡果不足惜,卻給世界環(huán)境...
    茶點故事閱讀 41,482評論 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧规伐,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 32,023評論 0 22
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間锁摔,已是汗流浹背怔蚌。 一陣腳步聲響...
    開封第一講書人閱讀 33,149評論 1 272
  • 我被黑心中介騙來泰國打工杖狼, 沒想到剛下飛機(jī)就差點兒被人妖公主榨干…… 1. 我叫王不留绿聘,地道東北人浅萧。 一個月前我還...
    沈念sama閱讀 48,409評論 3 373
  • 正文 我出身青樓己儒,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當(dāng)晚...
    茶點故事閱讀 45,086評論 2 355