flutter在iOS项目中的集成

作者: 万年老参 | 来源:发表于2023-06-28 16:09 被阅读0次

背景介绍: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工程如下所示:

image.png
若有报错:根据错误类型做对应处理,一般分为以下几种错误类型
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。
添加swift依赖.png
2,集成到iOS项目中:

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

截屏2022-06-27 上午10.08.47.png
2.2 将iOS项目和flutter项目按照以下位置关系置于同一文件夹下。(符合上一步中的路径关系) image.png
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];
    }
}

相关文章

网友评论

    本文标题:flutter在iOS项目中的集成

    本文链接:https://www.haomeiwen.com/subject/givoydtx.html