iOS原生集成Flutter开发环境

目前对于Flutter开发来说,主要的场景还是Native和Flutter混合开发的模式,而如何正确的在Native中集成Flutter则是我们的第一步。

现在网上关于Flutter集成的文章还是很多的,但是大多数还是不够详细,而且同样的方式去集成的话没办法集成成功。在这里主要分享一下自己的集成经验。

尝试的几种集成方式:

1、手动集成,手动去进行每一步的环境配置

2、参考闲鱼的集成方案,使用开源组件Flutter-boot集成

3、使用cocoapods集成

对于前两种方式,目前没有能成功的去配置好集成的环境(可能是姿势不对吧~)。而第三种方式,虽然也经历了一点小波折,但是最后还是成功的集成了开发环境。下面会对前两种失败的经历做一个简要描述,接着会着重介绍下第三种方式的集成过程。

1、手动集成,手动去进行每一步的环境配置(目前不能支持插件生效):

1)引入Flutter Module模块

打开终端,进入项目“Flutter_Code”的根目录,执行以下命令

cd Flutter_Code

flutter create -t module flutter_app

完成后,会生成名为flutter_app的文件夹,其和ios、android项目同级

2)创建依赖配置文件

打开iOS工程,在工程目录下新建文件夹(此文件夹的位置没有要求),用以保存配置文件,根据官网,需要创建三个配置文件:Flutter.xcconfig、Debug.xcconfig、Release.xcconfig。如图:


图1


图2

在Flutter.xcconfig中填写:

//这里填写建立的flutter module 的 Generated.xcconfig的路径,添加flutter的依赖关系

#include "../flutter_module/.ios/Flutter/Generated.xcconfig"

ENABLE_BITCODE=NO

在Debug.xcconfig中填写:

#include "Flutter.xcconfig"

在Release.xcconfig中填写:

#include "Flutter.xcconfig"

FLUTTER_BUILD_MODE=release

Ps:如果工程中用cocopods管理,则需要在Debug.xcconfig、Release.xcconfig中添加pod的路径

准备好上述xcconfig文件后,需要到PROJECT中的Configurations中设置相关配置,将对应的targer设置成前面生成的xcconfig文件,Debug选择Debug.xcconfig,Release用Release.xcconfig。如图:


图3

Ps:在进行打包时,无论是Debug还是Release,都需要切换到Release.xcconfig,否则会报错

3)为编译Dart引入相关脚本

在工程的Build Phase中新建一个Script Phase,用于运行Flutter脚本

新建Run Script Phase后,名字改为了“Flutter load”,需要移动其位置,需要在Dependencies之后(如上图),如果用cocoapods管理工程,则需要在Check Pod项目后。

在”Flutter load”里,在脚本框内,需要写入以下代码,用于加载Flutter的xcode_backend脚本:

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build


图4

4)修改Flutter SDK脚本:

这一步至关重要,因为每次修改main.dart文件后,都需要Command+B后才能生效,而进行Command+B后会生成、更新App.framework、engine、flutter_assets文件,所以这三个文件的依赖关系一定要添加正确,而且要保证每次编译工程时,所依赖的这三个文件都能即时更新。

4.1)默认情况下Xcode Run Script编译好的Framework并不在项目中,而在我们创建的flutter module文件夹下(一般路径是./ios/Flutter/)

4.2)而在Flutter脚本代码中有判断,文件生成的目录,需要注释掉相应的代码才能让其生成在当前的目录中

4.3)终端执行命令:

open $FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh

4.4)打开Flutter脚本后,注释掉以下代码:


图5

5)生成、添加Framework

完成上述配置后,使用Xcode编译工程(Command+B),编译成功后,会在iOS工程文件夹中生成一个Flutter文件夹。

项目中添加Flutter文件的依赖。进入项目目录,选择Add Files to ‘xxx’依次去添加App.framework、engine、flutter_assets三个内容,

(注意:下述图中第2步,“.ios”是隐藏文件,可以使用快捷键“Command+Shift+.”来使之显示)

其中,添加App.framework、engine两项内容时,需要选择“Copy Items If needed”、“Create groups”

第三项,flutter_assets添加是,需要选择“Copy Items If needed”、“Create folder references”

上述操作完成后,文件夹目录是这样的,注意:flutter_assets是蓝色文件,engine是黄色文件

然后,添加App.framework、Flutter.framework。

注意:添加成功后将Embed选择为“Embed & Sign”,否则启动程序会崩溃。

6)修改Generated.xcconfig文件路径:

一般自动生成的Generated.xcconfig中的路径都是绝对路径,如果更改项目名称或位置,会找不到依赖的Flutter文件而导致编译失败。

解决方法:

将划红线部分的路径替换为”../”,表示在flutter_module上一级的文件夹中查找对应的路径,如图:

图6

接下来就是在AppDeleaget.h、.m中添加相应的代码即可正常编译使用。

注意:通过这种方式集成后,去使用Flutter的插件时(如image_picker),插件无法生效。这是因为插件生效需要引用GeneratedPluginRegistrant文件,而目前这种方式并没有去引用,所以插件无法生效。

扩展:可以尝试通过cocoapod的方式,将flutter module中的GeneratedPluginRegistrant文件进行打包成framework,然后引用到Native项目中,这样的话这种集成方式也可以使用。

最后这一步具体如何去做,这里就不再去分析了,大家有兴趣的话可以在研究一下。

原文参考链接:https://www.jianshu.com/p/10237bf13789


2、参考闲鱼的集成方案,使用开源组件Flutter-boot集成(目前通过官网的操作步骤集成后无法使用)

1)下载和使用工具flutter-boot

开源地址:https://github.com/alibaba-flutter/flutter-boot

下载安装flutter-boot必须使用npm(前端的包管理工具),常使用brew去下载,结果不行~

使用npm的过程中可能会报错,大家可以自行百度,一般情况下重新对npm进行更新、启动等操作后就OK了。

若是还无法正常安装flutter-boot,可以尝试在命令前加上sudo命令:

sudo npm install -g flutter-boot

2)下载成功后,通过flutter-boot去集成环境

一般情况下,我们直接通过终端进入项目的根目录,如这里的"Flutter_Native_0328",里边包含了ios、android项目。

此时,在终端输入以下命令:

flutter-boot init

终端会提示输入flutter工程名称,我们这里直接输入"app"(经过各种尝试,之后将flutter module命名为“app”时,才不会报错,可能和集成工具内部的命名有关吧)

接着会提示输入关联的iOS工程等,其他的按照提示操作即可,完成后目录结构如图,多出了名称为app的flutter module

图1

接下来的其他步骤按照官网知道即可。

但是我通过官网的知道去操作后,发现最终的Native项目(即ios项目)并没有和flutter关联起来,再下去就没法进行了,进行了各种资料的查找、各种尝试、或者在开源社区中求助,都未能能到有效的回应,暂时搁浅了......

不知道是不是中间哪里的操作姿势不对,有兴趣的可以在研究一下flutter-boot该怎么才能正确使用。


3、使用cocoapods集成

1)引入Flutter module模块

打开终端,进入项目“Flutter_Native_Mix_0330”的根目录,执行以下命令

cd Flutter_Native_Mix_0330

flutter create -t module flutter_module

完成后,会生成名为flutter_app的文件夹,其和ios、android项目同级

2)使用cocoapods

2.1)若当前项目中未使用cocoapods,则先进行安装https://cocoapods.org(若已安装,则跳过)

如果下载cocoapods失败,排查是不是“gem”工具的问题,一般都是简单的问题,可以自行百度解决

我目前使用的cocoapods版本为1.9.1,而Flutter SDK版本是1.12

2.2)若项目未使用cocoapods,则进行初始化(若已使用,则跳过)

进入ios项目文件夹,执行命令

pod init

完成后,会在ios项目文件夹下生成一个Podfile的文件。

2.3)接着,打开 Podfile 这个文件,添加以下代码

flutter_application_path = '../flutter_module/'

load File.join(flutter_application_path,'.ios','Flutter','podhelper.rb')

注意:这段代码得写到文件的顶部。这里使用相对路径,不要写绝对路径

例如,我的Podfile文件是这样的:

图2

添加完成后,在终端输入以下命令:

pod install

如图:

图3

会直接将Flutter的相关依赖和库的添加到iOS项目中。

2.4)接下来,打开ios项目,直接Command+B编译代码。

若当前没有导入插件,则直接编译成功。

若当前引入了插件,并使用GeneratedPluginRegistrant初始化插件,编译后,发现报错了,如下:

图3

这是因为使用cocoapods导入了Flutter相关的库,需要在Build Setting->Linking->Other Linker Flags,添加 $(inherited)

图4

这时候,能够看到,将Flutter相关的库导入了进来,插件也导入了。

此时,在编译工程,发现可以成功运行了。

3)添加新的插件

3.1)添加新的插件时,在pubspec.yaml中添加依赖后,进入flutter_module目录,在终端执行:

flutter pub get

会将插件下载下来,但是还不能立即使用。需要进入ios项目目录,终端输入命令:

pod install

执行这个命令,相当于更新了ios项目和flutter项目的依赖关系(新的插件引用)。更新过后,编译ios项目,新的插件就可以使用了。

ps:对于这种混合项目,建议使用flutter-boost插件来开发,这个插件是闲鱼的开源组件,会解决混合开发中遇到的大部分问题,很方便

4)项目路径修改为相对路径

若是多人开发时,或者自己重新拉取代码时,会重新命名本地项目文件夹名称,此时编译iOS项目会报错,如图:

图5

从这个错误可以看出来,我们在集成的时候,一些编译路径自动编译为了绝对路径,我们根据报错的信息,找到了是在编译以下脚本文件时,报错了,如图:

图6

我们根据路径找到对应的脚本文件后,打开发现“FLUTTER_APPLICATION_PATH”被定义为了绝对路径,如图:

图7

其项目名称和路径是写死的,因此我们把这里的路径改为相对路径即可,如下:

"FLUTTER_APPLICATION_PATH=../flutter_module"

除此之外,我们还需要把这个路径下“../flutter_module/.ios/Flutter/Generated.xcconfig”,Generated.xcconfig文件中的绝对路径修改为相对路径。

至此,我们可以随意命名项目文件夹,程序都可以正常编译。

研究了许久集成完后,就大功告成了。


4、使用Xcode集成Flutter的Framework

除了上面的方法,你也可以创建必备的 frameworks,手动修改既有 Xcode 项目,将他们集成进去。当你组内其它成员们不能在本地安装 Flutter SDK 和 CocoaPods,或者你不想使用 CocoaPods 作为既有应用的依赖管理时,这种方法会比较合适。但是每当你在 Flutter module 中改变了代码,都必须运行 以下终端代码

首先,在已经创建了flutter_module的前提下,我们在ios的项目文件夹内新建文件夹Flutter,主要用来保存Flutter相关的framework。

接着,在终端执行以下命令:

cd flutter_module

flutter build ios-framework --output=/yourPath/ios/Flutter/

参考链接:https://flutter.cn/docs/development/add-to-app/ios/project-setup

https://flutter.cn/docs/development/add-to-app/android/project-setup

经历了各种尝试,最终还是尝试使用cocoapods的方式来集成成功了。而且相比较来看,第一种方式步骤繁琐,而且目前没法有效支持插件;第二种方式虽然官网介绍说简单几步就可完成集成,但是实际操作后发现并不简单,官方介绍也含糊不清,开源社区相比较使用的人数也不多,也比较麻烦;而这第三、四种方式,集成的方式简单,步骤少,出错率少,兼容性高,而且灵活性也不错。

因此,最后两种方式无疑是目前最好的选择。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 159,219评论 4 362
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,363评论 1 293
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,933评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 44,020评论 0 206
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,400评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,640评论 1 219
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,896评论 2 313
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,597评论 0 199
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,327评论 1 244
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,581评论 2 246
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,072评论 1 261
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,399评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,054评论 3 236
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,083评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,849评论 0 195
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,672评论 2 274
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,585评论 2 270

推荐阅读更多精彩内容