背景介绍:OC的iOS项目,集成flutter模块
注意,下文中"iOS项目"指将要集成flutter的原生项目,“.ios项目”指由flutter工程生成的被集成项目
准备工作:
1,flutter工程(第三方的,或者其他同事开发的,需要集成到iOS项目的flutter工程)
2,本地flutter环境,建议与flutter工程的版本保持一致,不然后续会有兼容问题
3,iOS工程。
4,cocoapods环境
集成项目:
1,flutter项目编译:
终端cd到flutter路径内,执行命令:flutter run 。
无报错:则生成了可用于集成的.iOS项目.ios文件夹默认为隐藏状态。生成后的flutter工程如下所示:

若有报错:根据错误类型做对应处理,一般分为以下几种错误类型
1.1.1, flutter项目代码问题:使用相关开发工具检查flutter代码(比如:vscode,添加flutter和dark插 件后。进行debug),flutter项目与本地flutter版本不一致时,有时也会导致此问题。
1.1.2,.ios项目内问题:检查.ios项目build有什么问题,(可以使用xcode打开.ios项目)检查开发账户和证书配置是否正确,检查cocoapods是否正常集成,检查第三方库是否需要项目添加swift依赖,cd进入.iOS路径下,cocoapod重新install。

2,集成到iOS项目中:
2.1 修改iOS项目中的Podfile文件:(若iOS项目未使用cocoapods,需要新建Podfile文件,)
增加以下选中内容:主要目的是按照所编辑路径将上一步中的.ios项目集成到iOS项目中

2.2 将iOS项目和flutter项目按照以下位置关系置于同一文件夹下。(符合上一步中的路径关系)

2.3,pod刷新 终端cd到iOS项目路径下,执行pod install(若有swift依赖问题见1.1.2配图)。
完成项目集成后,可能后续打包会出现Bitcode设置问题,将pod中TARGETS相关库的Enable Bitcode设置为NO即可。
3,代码调用:
代码部分主要分为两部分:
1,配置启动器。
目前项目使用FlutterEngineGroup用以实现复合的flutter页面集成。单一flutter项目也可以使用
FlutterEngine
在Appdelegate.h中添加:
#import <Flutter/Flutter.h>
//@property (nonatomic,strong) FlutterEngine *flutterEngine;
@property (nonatomic,strong) FlutterEngineGroup *flutterEngineGroup;
在Appdelegate.m中添加:
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
.....
self.flutterEngineGroup = [[FlutterEngineGroup alloc] initWithName:@"flutterGroupName" project:NULL];
//若只有单一flutter页面,也可以用以下代码
//FlutterEngine:
// self.flutterEngine = [[FlutterEngine alloc] initWithName:@"my flutter engine"];
// [self.flutterEngine run];
// [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return YES;
}
2,生成页面及通道。
以flutter里面提供了页面page_one,通道名称page_One_channal为例子。
flutter页面为继承FlutterViewController的类。
自定义类:XYFlutterViewController:
XYFlutterViewController.h代码:
#import <Flutter/Flutter.h>
NS_ASSUME_NONNULL_BEGIN
@interface XYFlutterViewController : FlutterViewController
//返回flutter页面
+(XYFlutterViewController *)flutterPageWithName:(NSString *)name;
@end
NS_ASSUME_NONNULL_END
FlutterMethodChannel:通道,flutter与原生交互依赖通道,一般每个flutter页面维护一个通道
setMethodCallHandler:给通道注册方法,调用原生内容
invokeMethod:原生使用通道调用flutter内的方法。
XYFlutterViewController.m代码:
#import "AppDelegate.h"//主要用来获取全局flutterEngineGroup
#import <FlutterPluginRegistrant/FlutterPluginRegistrant-umbrella.h>
#import "XYFlutterViewController.h"
@interface XYFlutterViewController ()
@property (strong,nonatomic)FlutterMethodChannel *Channel;
@property (strong,nonatomic)NSMutableDictionary *flutterMCDic;//FlutterMethodChannel集合
@end
@implementation XYFlutterViewController
//懒加载flutter的MethodChannel,有则取,无则创建
/*
name为flutter约定的的通道名称
*/
-(FlutterMethodChannel *)flutterMethodChannelWithName:(NSString *)name
{
if (self.flutterMCDic[name]) {
return self.flutterMCDic[name];
}
FlutterMethodChannel *notifationChannel = [FlutterMethodChannel methodChannelWithName:name binaryMessenger:self];
[self.flutterMCDic setObject:notifationChannel forKey:name];
return notifationChannel;
}
-(NSMutableDictionary *)flutterMCDic
{
if (!_flutterMCDic) {
_flutterMCDic = [NSMutableDictionary new];
}
return _flutterMCDic;
}
-(void)dealloc
{
[self.flutterMCDic removeAllObjects];
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
/*
name为flutter提供的页面名称,以page_one页面为例子,通道名称为page_One_channal
*/
+(XYFlutterViewController *)flutterPageWithName:(NSString *)name
{
FlutterEngine *flutterEngine = [((AppDelegate *)UIApplication.sharedApplication.delegate).flutterEngineGroup makeEngineWithEntrypoint:name libraryURI:nil];
[GeneratedPluginRegistrant registerWithRegistry:flutterEngine];
XYFlutterViewController *flutterViewController = [[XYFlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
//页面添加通道,page_One参数为futter中设置的
if ([name isEqualToString:@"page_One"]) {
[flutterViewController addActionWithName:@"page_One_channal"];
}
}
/*
name为flutter约定的的通道名称
*/
-(void)addActionWithName:(NSString *)name
{
//call.method flutter方法名
//call.arguments flutter给到的参数
FlutterMethodChannel *notifationChannel = [self flutterMethodChannelWithName:name];
//设置回调:以方法1:userChannel 方法2:jumpChannel为例
[notifationChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
//userChannel方法:需要数据回调:
if ([@"userChannel" isEqualToString:call.method]) {
NSDictionary *dic = @{
@"userId":@"****",
};
result(dic);
}else if ([@"jumpChannel" isEqualToString:call.method]) {
//jumpChannel方法:从flutter页面调用原生页面
UIViewController *vc = [UIViewController new];
vc.hidesBottomBarWhenPushed = YES;
[self.navigationController pushViewController:vc animated:YES];
}
}];
}
//主动调用flutter方法:
-(void)flutter_actionWithChannleName:(NSString *)channel Name:(NSString *)name
{
FlutterMethodChannel *notifationChannel = [self flutterMethodChannelWithName:channel];
if([name isEqualToString:@"refrish"]){
NSDictionary *dic = @{
@"userId":@"****",
};
//通道去调用flutter方法
[notifationChannel invokeMethod:name arguments:dic];
}
}
网友评论