iOS混合Flutter初探

由于最近公司项目里面要用到Flutter,故研究了一番iOS和Flutter是如何在一起工作的。下面我们就一步步的来介绍一下:
开发环境
在你心爱的Mac上面安装好Flutter 1.12.13+hotfix.8 • channel stable •Xcode 11.2.1

提示:Flutter 支持到iOS8以上。

首先要创建一个iOS项目ios_flutter_hybrid

这里就不再详细介绍该项目是如何创建的了。
然后集成flutter_module到iOS项目中,flutter 可以作为一个framework嵌入到现有的iOS项目中。
要将flutter嵌入到现有的iOS工程中,首先要创建一个flutter_module,它的目录位置最好和项目目录是平行的。执行如下命令:

1
2
cd ios_flutter_hybrid
flutter create -t module flutter_module

出现如下log就说明执行成功了:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
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... 2.0s
Wrote 12 files.

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

嵌入flutter module 到现有工程中
有两种方式将Flutter嵌入到项目中
1.使用pod install 安装(推荐使用) (配置一下podfile下面会讲解)
2.你编译好一个framework,然后手动嵌入到项目中,并且好手动更新编译配置。
注意
和Flutter 混合的应用不可以在simulator 上面运行Release模式,因为flutter 不支持为Dart代码提前输出x86二进制文件。你可以在模拟器或真机上面运行Release模式。

我选择的是使用pod来嵌入flutter framework.

需要说明的是flutter 模块的目录和应用程序的目录是平行的,否则可能需要调整相对路径。目录结构如下:

1
2
3
4
5
6
7
some/path/
├── flutter_module/
│ └── .ios/
│ └── Flutter/
│ └── podhelper.rb
└── ios_flutter_hybrid/
└── Podfile

如果新创建的项目没有podfile 就创建一个podfile。然后在podfile里面添加如下代码:

1
2
3
4
5
6
flutter_application_path = '../flutter_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'ios_flutter_hybrid' do
install_all_flutter_pods(flutter_application_path)
end

对于每一个需要嵌入flutter的podfile 目标,调用 install_all_flutter_pods(flutter_application_path) 方法。
接下来只需要执行 pod install 即可。

注意
当你在pubspec.yaml中修改了flutter plugin的依赖关系,在flutter module目录下运行flutter pub get 命令来更新podhelper.rb脚本读取的插件列表。然后执行pod install 来安装更新。
podhelper.rb脚本将你的plugin、Flutter.framework、App.framework嵌入到工程中。
此时,你就开打开ios_flutter_hybrid.xcworkspace 来运行混合好的项目了。

添加一个flutter 页面进入到上面的工程中
首先要在Appdelegate里面创建一个FlutterEngine如下代码:

1
2
3
4
5
6
@import UIKit;
@import Flutter;

@interface AppDelegate : FlutterAppDelegate // More on the FlutterAppDelegate below.
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end

实现部分:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import "AppDelegate.h"
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Used to connect plugins.
@interface AppDelegate ()
@end

@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
self.flutterEngine = [[FlutterEngine alloc] initWithName:@"my flutter engine"];
// Runs the default Dart entrypoint with a default Flutter route.
[self.flutterEngine run];
[GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

接下来我们在ViewController里面写一个点击事件来吊起一个Flutter页面。在ViewController的viewDidLoad方法中添加如下代码:

1
2
3
4
5
6
7
8
9
10
11
12
13
- (void)viewDidLoad {
[super viewDidLoad];

// Make a button to call the showFlutter function when pressed.
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:@selector(showFlutter)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Show Flutter!" forState:UIControlStateNormal];
button.backgroundColor = UIColor.blueColor;
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}

同时实现一个showFlutter方法:

1
2
3
4
5
6
7
- (void)showFlutter {
FlutterEngine *flutterEngine =
((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
FlutterViewController *flutterViewController =
[[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
[self presentViewController:flutterViewController animated:YES completion:nil];
}

此时运行一下工程查看效果。不出意外的话你会成功的调起来一个Flutter 页面。

混合项目如何调试

混合的项目也是可以使用flutter的热更新以及热重启的。接下来我们就介绍一下如何使用这个功能。
首先将混合好的项目运行到手机上,进入flutter页面。
然后cd 到flutter_module目录下,执行flutter attach命令。如果打印的有如下日志,则说明成功了:

1
2
3
4
5
6
 Syncing files to device Charles的iPhone...                               
4,694ms (!)

🔥 To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R".
An Observatory debugger and profiler on Charles的iPhone is available at: http://127.0.0.1:1024/RkN8tMSDSoE=/
For a more detailed help message, press "h". To detach, press "d"; to quit, press "q".

接下来就可以愉快的开发调试界面了。

本文Demo代码

下篇文章我们一起来探讨flutter 和 原生iOS代码之间是如何通信的。

欢迎勘误!

谢谢您的支持!