写点什么

Flutter 混合开发 (二):iOS 项目集成 Flutter 模块详细指南

用户头像
Android架构
关注
发布于: 43 分钟前

[](


)创建 Flutter module


===================================================================================


假如 iOS 项目的路径是这样的:flutter/flutter_hybrid/iOS Project,那么我们需要在 iOS Project 上一层目录 flutter_hybrid 中创建 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 就表示我们项目创建好了。整个 module 目录和原生 Flutter 基本一样,主要就是 Android、iOS 的宿主工程和 lib 目录以及 pubspec.yaml 文件。


[](


)添加 Flutter module 依赖


=====================================================================================


为 iOS 项目添加依赖需要使用 CocoaPods,如果你还没有用到 CocoaPods,可以参考[https://cocoapods.org/](


)上面的说明来安装 CocoaPods。


如果你的项目之前没有使用过 cocoapods,那么需要进行初始化生成 podfile 文件,进入 iOS 项目的根目录执行:


pod init


然后打开 podfile 文件,进行配置:

配置

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


配置添加好后在项目根目录运行以下命令进行安装:


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.


这里我们看到有三个依赖安装完成了。并提醒我们关闭当前项目,在根目录下面使用 iOSFlutterHybrid.xcworkspace 来打开运行项目。这里可能很多人在执行命令的时候会发现提示 0 个依赖完成。这里有可能是你的 Xcode 版本的问题。因为 Flutter 要求最低版本是 10.2 及以上。


当在 flutter_module/pubspec.yaml 中添加一个 Flutter 插件时,需要在 flutter_module 目录下运行:


flutter packages get


来刷新 podhelper.rb 脚本中的插件列表,然后在 iOS 目录下运行:


pod install


这样 podhelper.rb 脚本才能确保添加的插件和 Flutter.framework 能够添加到 iOS 项目中。


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


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


Build Settings->Build Options->Enable Bitcode



flutter 以前的版本是需要添加 build phase 以构建 Dart 代码,但是最新的版本已经不需要添加了,可以自动构建。


[](


)调用 Flutter module


===================================================================================


Flutter 为我们提供了两种调用方式:FlutterViewController 和 FlutterEngine,FlutterEngine 在使用的时候会有一些问题,将在下文进行说明。

[](

)FlutterViewController 方式:


我们打开 ViewController.m 文件,在里面添加一个加载 flutter 页面的方法并且添加一个按钮看来调用:


#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];


//设置路由参数


[flutterViewController setInitialRoute:@"route2"];


[self presentViewController:flutterViewController animated:false completion:nil];


}


@end


当我们运行项目点击加载 Flutetr 按钮时,将会调用 Flutter 页面。和 Android 项目集成一样,这里的 setInitialRoute 可以设置一个 json 数组来传递需要交互的参数。并在 Flutter 中使用 window.defaultRouteName 来获取传递的参数。

[](

)FlutterEngine 方式:


我们需要在 AppDelegate 中对 FlutterEngine 进行初始化。打开 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 中调用:


  • (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];


}


当我们运行项目点击加载 Flutter 按钮时,将会调用 Flutter 页面。前文讲到使用 FlutterEngine 会有问题,就是我们 setInitialRoute 传递的参数在 flutter 中永远获取到的都是 “/” ,这个是 Fltter SDK 的一个 Bug,所以如果必须依赖 setInitialRoute,还是使用 FlutterViewController 的形式来加载 Flutter 模块。


[](


)热重启/重新加载


===========================================================================


大家在写纯 Flutter 应用的时候,知道是有热重启/重新加载功能的,但是在做混合开发的过程中,你会发现热重启/重新加载功能失效了。那么如何在混合开发中开启热重启/重新加载功能呢?


  • 首先接入我们的设备或者模拟器

  • 将我们的 App 关闭,退出后台,在 terminal 中运行 flutter attach 命令


$ flutter attach


Waiting for a connection from Flutter on Android SDK built for x86...


复制代码此时就在等待设备的连接。这里要注意的是,如果电脑连接了多台设备需要使用 -d 命令来指定一台设备,参数为设备的 id。


flutter attach -d '你的设备 id'


然后启动我们的应用会看到控制台输出:


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".


这样就表示我们连接成功了。在输出的日志中也告诉了我们如何使用热重启/重新加载功能。


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


r : 热加载;


R : 热重启;


h : 获取帮助;


d : 断开连接;


q : 退出;


这里的的 d 和 q 的命令都有退出调试,区别在于 d 命令只是单纯的断开而 q 命令会将应用退到后台。


[](


)调试 Dart 代码


===========================================================================


同样在混合开发过程中我们如何调试 dart 代码呢?


  • 关闭我们的应用

  • 点击 Android Studio 工具栏上的 Flutter Attach 按钮(需要安装 Flutter 与 Dart 插件)



  • 启动我们的应用


接下来就可以像调试普通 Flutter 项目一样来调试混合开发模式下的 Dart 代码了。


[](


)总结


=====================================================================


本文主要是讲解了 iOS 集成 Flutter 项目的步骤,其中也遇到了一些问题,由于我的 Xcode 版本较低,在集成的过程中 iOS 项目的依赖一直失败。最后才发现是 Xcode 的版本问题。


**# 前言


前一篇文章讲解了 Android 原生工程如何集成 Flutter 项目的具体过程,[Flutter 混合开发(一):Android 项目集成 Flutter 模块详细指南](


) ,本篇将带着大家来一起学习原生 iOS 项目如何集成 Flutter。


因为每个版本的集成逻辑都是有差别的,所以这里交代下本篇文章的集成版本:


Flutter (channel dev,v1.10.16)


dart (v2.7.0)


Xcode (v11.2)


cocoapds (1.8.4)


[](


)创建 Flutter module


===================================================================================


假如 iOS 项目的路径是这样的:flutter/flutter_hybrid/iOS Project,那么我们需要在 iOS Project 上一层目录 flutter_hybrid 中创建 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 就表示我们项目创建好了。整个 module 目录和原生 Flutter 基本一样,主要就是 Android、iOS 的宿主工程和 lib 目录以及 pubspec.yaml 文件。


[](


)添加 Flutter module 依赖


=====================================================================================


为 iOS 项目添加依赖需要使用 CocoaPods,如果你还没有用到 CocoaPods,可以参考[https://cocoapods.org/](


)上面的说明来安装 CocoaPods。


如果你的项目之前没有使用过 cocoapods,那么需要进行初始化生成 podfile 文件,进入 iOS 项目的根目录执行:


pod init


然后打开 podfile 文件,进行配置:

配置

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

用户头像

Android架构

关注

还未添加个人签名 2021.10.31 加入

还未添加个人简介

评论

发布
暂无评论
Flutter混合开发(二):iOS项目集成Flutter模块详细指南