Flutter与原生的混合开发笔记

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 

NS_ASSUME_NONNULL_BEGIN

@interface XKFluttersViewController : FlutterViewController

@end

NS_ASSUME_NONNULL_END

FlutterViewController.m

#import "XKFluttersViewController.h"
#import "XKFlutterHandler.h"

@interface XKFluttersViewController ()

@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 

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

2.FlutterView的问题

现目前dart文件只能加载在FlutterViewController上的View,在github上翻看了一下源码,发现有个FlutterView的类,但是SDK中没公开出来,所以如果想要NativeView和FlutterView在同一个控制器中组合展示则可以把FlutterViewController的View添加到自身ViewController的View上再重设frame即可

你可能感兴趣的:(Flutter与原生的混合开发笔记)