Flutter iOS原生集成流程
我这儿用的Flutter版本是1.7.8+hotfix.4,在与最新版本在SDK中有些许区别
一、Flutter 提供的 Native Flutter 混合工程方式
1. 创建 Flutter 工程
请自行 百度/Google Flutter 安装教程,安装Flutter。然后到任意目录下执行flutter create -t module my_flutter,"my_flutter" 是要创建的 Flutter 工程的名称。
2. 通过 Cocoapods 将 Flutter 引入 现有 Native 工程
在Podfile添加以下下代码
flutter_application_path = "xxx/xxx/my_flutter"
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
执行pod install
3. 修改 Native 工程
打开Xcode工程,选择要加入 Flutter App 的 target,选择 Build Phases,点击顶部的 + 号,选择 New Run Script Phase,然后输入以下脚本
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
4. 编译通过,开始编写FlutterViewController代码
FlutterViewController.h
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface XKFluttersViewController : FlutterViewController
@end
NS_ASSUME_NONNULL_END
FlutterViewController.m
#import "XKFluttersViewController.h"
#import "XKFlutterHandler.h"
@interface XKFluttersViewController ()<FlutterPluginRegistry>
@property (strong, nonatomic) FlutterMethodChannel* batteryChannel;
@property (assign, nonatomic) BOOL isFirst;
@end
@implementation XKFluttersViewController
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
_isFirst = YES;
[self initFlutter];
}
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
}
- (void)viewDidAppear:(BOOL)animated {
[super viewDidAppear:animated];
[UIView animateWithDuration:.25f animations:^{
self.view.frame = CGRectMake(0, [SYHandler statusBarHeight] , SCREEN_WIDETH, SCREEN_HEIGHT - [SYHandler statusBarHeight]);
}];
if (_isFirst) {
_isFirst = NO;
// 与flutter通信,通知flutter页面已经显示
[_batteryChannel invokeMethod:@"onResume" arguments:nil];
}
}
- (void)initFlutter {
NSString* methodName = @"xiaoka";
_batteryChannel = [FlutterMethodChannel methodChannelWithName:methodName
binaryMessenger:self];
WS(weakSelf);
[_batteryChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
// TODO
SS(strongSelf, weakSelf)
[XKFlutterHandler handleCallWithMethod:call.method
arguments:call.arguments
controller:strongSelf
handler:result];
}];
}
- (void)dealloc {
self.batteryChannel = nil;
NSLog(@"释放 FlutterViewController");
}
@end
XKFlutterHandler.h
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface XKFlutterHandler : NSObject
/**
* 处理回调方法和参数
@param method 方法
@param arguments 参数
@param controller 控制器
@param handler block
*/
+ (void)handleCallWithMethod:(NSString *)method
arguments:(id)arguments
controller:(UIViewController *)controller
handler:(FlutterResult)handler;
@end
XKFlutterHandler.m
#import "XKFlutterHandler.h"
@implementation XKFlutterHandler
+ (void)handleCallWithMethod:(NSString *)method
arguments:(id)arguments
controller:(UIViewController *)controller
handler:(FlutterResult)handler
{
// 与flutter约定的方法名
if ([method isEqualToString:@"getAppKey"]) {
// 获取appkey
NSString* appkey = @"appkey";
// 返回数据给Flutter
handler(appkey);
}
}
至此就可以快乐的使用flutter的各种页面了
5.热重载
在run Xcode项目时,现在vs或as中把flutter的debug指定端口上,然后在Xcode项目启动时Flutter.framework就可以连接并及时刷新页面
flutter attach --debug-port=端口号
二、在开发过程中的注意事项⚠️
1. setInitialRouter路由失效
因为在我的需求里面是: 在iOS现有工程集成flutter项目,然后可以跳转到任意的flutter业务页面。
// 使用全局引擎初始化
FlutterViewController* flutterViewController = [[FlutterViewController alloc] initWithEngine:appdelegate.engine nibName:nil bundle:nil];
// (无效)
[flutterViewController setInitialRouter:@"test"];
// (会有push的效果)
[flutterViewController pushRoute:@"test"];
// 使用默认初始化 (有效)
FlutterViewController* flutterViewController = [[FlutterViewController alloc] init];
[flutterViewController setInitialRouter:@"test"];