在 Flutter项目中集成完 flutter boost,并且已经使用了 flutter boost进行了路由管理,这时如果需要和iOS混合开发,这时就要到 原生端进行集成。

注意:之前建的项目必须是 Flutter module项目,并且原生项目和flutter module项目在同一个文件夹下面

下面是原生端集成 flutter boost的步骤:

  • 在原生项目的 Podfile文件中添加如下代码
# Uncomment the next line to define a global platform for your project
platform :ios, '12.0'


flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')


target 'FlutterList' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for FlutterList
  install_all_flutter_pods(flutter_application_path)
  

  pod 'Masonry', '1.0.2'
  
end


post_install do |installer|
  flutter_post_install(installer) if defined?(flutter_post_install)
end

填写完后指向 pod install。此时项目的pod目录下面就会出现 flutter相关的库
在这里插入图片描述
到此就完成 flutter混合开发的集成工作,接下来就是需要 编写使用代码

  • 编写混合开发代码
    这里没有跟着flutter boost 官网进行集成 https://github.com/alibaba/flutter_boost/blob/master/docs/install.md 创建代码,稍微进行了些改进。

  • HYFlutterBoostDelegate

  • HYFlutterViewContainer

  • HYFlutterViewController
    分别创建了以上代码,并且在AppDelegate 中使用 FlutterBoost

  • HYFlutterBoostDelegate

import Foundation
import flutter_boost

class HYFlutterBoostDelegate: NSObject, FlutterBoostDelegate {
    
    ///您用来push的导航栏
    var navigationController:UINavigationController? {
        return UINavigationController.topNavigationController()?.navigationController
    }

    ///用来存返回flutter侧返回结果的表
    var resultTable:Dictionary<String,([AnyHashable:Any]?)->Void> = [:];
    
    func pushNativeRoute(_ pageName: String!, arguments: [AnyHashable : Any]!) {

        //可以用参数来控制是push还是pop
        let isPresent = arguments["isPresent"] as? Bool ?? false
        let isAnimated = arguments["isAnimated"] as? Bool ?? true
        //这里根据pageName来判断生成哪个vc,这里给个默认的了
        let targetViewController = UIViewController()
        
        // 这里也可以使用路由进行跳转
        
        if(isPresent){
            self.navigationController?.present(targetViewController, animated: isAnimated, completion: nil)
        }else{
            self.navigationController?.pushViewController(targetViewController, animated: isAnimated)
        }
    }
    
    func pushFlutterRoute(_ options: FlutterBoostRouteOptions!) {
        let vc:HYFlutterViewController = HYFlutterViewController()
        vc.setName(options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque)
        vc.hidesBottomBarWhenPushed = true
        //对这个页面设置结果
        resultTable[options.pageName] = options.onPageFinished;
        if let nav = navigationController  {
            nav.pushViewController(vc, animated: true)
        }
        
    }
    
    
    func popRoute(_ options: FlutterBoostRouteOptions!) {
        //如果当前被present的vc是container,那么就执行dismiss逻辑
        if let vc = self.navigationController?.presentedViewController as? HYFlutterViewController, vc.uniqueIDString() == options.uniqueId{
            
            //这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题
            //所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑
            if vc.modalPresentationStyle == .overFullScreen {
                
                //这里手动beginAppearanceTransition触发页面生命周期
                self.navigationController?.topViewController?.beginAppearanceTransition(true, animated: false)
                
                vc.dismiss(animated: true) {
                    self.navigationController?.topViewController?.endAppearanceTransition()
                }
            }else{
                //正常场景,直接dismiss
                vc.dismiss(animated: true, completion: nil)
            }
        }else{
            self.navigationController?.popViewController(animated: true)
        }
        //否则直接执行pop逻辑
        //这里在pop的时候将参数带出,并且从结果表中移除
        if let onPageFinshed = resultTable[options.pageName] {
            onPageFinshed(options.arguments)
            resultTable.removeValue(forKey: options.pageName)
        }
    }
    
}
  • HYFlutterViewContainer
#import <flutter_boost/FlutterBoost.h>

NS_ASSUME_NONNULL_BEGIN

@interface HYFlutterViewContainer : FBFlutterViewContainer

@end

NS_ASSUME_NONNULL_END
#import "HYFlutterViewContainer.h"

@interface HYFlutterViewContainer (){
    UINavigationBar *_bar;
}

@property (nonatomic)BOOL navigationBarHidden;
@property (nonatomic, strong) FBVoidCallback removeEventCallback;

@end

@implementation HYFlutterViewContainer

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
}

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.navigationController setNavigationBarHidden:YES animated:animated];
}

/// 设置这个container对应的从flutter过来的事件监听
-(void)setupEventListeningFromFlutter{
    __weak typeof(self) weakSelf = self;
    // 为这个容器注册监听,监听内部的flutterPage往这个容器发的事件
    self.removeEventCallback = [FlutterBoost.instance addEventListener:^(NSString *name, NSDictionary *arguments) {
        __strong typeof(self) strongSelf = weakSelf;
        //事件名
        NSString *event = arguments[@"event"];
        //事件参数
        NSDictionary *args = arguments[@"args"];
        
        if ([event isEqualToString:@"enablePopGesture"]) {
            // 多page情况下的侧滑动态禁用和启用事件
            NSNumber *enableNum = args[@"enable"];
            BOOL enable = [enableNum boolValue];
            //右滑控制
//            strongSelf.fd_interactivePopDisabled = !enable;
        }
    } forName:self.uniqueId];
}

- (BOOL)navigationBarHidden {
    return YES;
}

- (UINavigationBar *)navBar
{
    if (!_bar) {
        _bar = [UINavigationBar new];
    }
    return _bar;
}

- (BOOL)shouldAutorotate
{
    return NO;
}

- (UIInterfaceOrientationMask)supportedInterfaceOrientations
{
    return UIInterfaceOrientationMaskPortrait;
}


@end
  • HYFlutterViewController
#import <UIKit/UIKit.h>
#import "HYFlutterViewContainer.h"


@interface HYFlutterViewController : UIViewController

@property (nonatomic, strong) HYFlutterViewContainer *container;

- (NSString *)uniqueIDString;

- (void)setName:(NSString *)name uniqueId:(NSString *)uniqueId params:(NSDictionary *)params opaque:(BOOL) opaque;

@end

#import "HYFlutterViewController.h"
#import <Masonry/Masonry.h>
#import "UINavigationController+HY.h"


@interface HYFlutterViewController ()

@end

@implementation HYFlutterViewController


- (void)setName:(NSString *)name uniqueId:(NSString *)uniqueId params:(NSDictionary *)params opaque:(BOOL) opaque {
    _container = [HYFlutterViewContainer new];
    [_container setName:name uniqueId:uniqueId params:params opaque:opaque];
}


- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.
    
    // 隐藏导航栏
    [self.container.navigationController setNavigationBarHidden:YES animated:YES];
    
    [self addChildViewController:_container];
    [_container didMoveToParentViewController:self];
    
    [self.view addSubview:_container.view];
    [_container.view mas_makeConstraints:^(MASConstraintMaker *make) {
        make.edges.mas_equalTo(UIEdgeInsetsZero);
    }];
}



- (NSString *)uniqueIDString {
    return self.container.uniqueIDString;
}

- (void)dealloc {
    [_container removeFromParentViewController];
    [_container didMoveToParentViewController:nil];
}

@end

  • AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    HYFlutterBoostDelegate* delegate = [[HYFlutterBoostDelegate alloc]init];
    
    [FlutterBoost.instance setup:application delegate:delegate callback:^(FlutterEngine *engine) {
        NSLog(@"FlutterBoost 开始操作");
        
    }];
    
    self.window = [[UIWindow alloc]initWithFrame:[UIScreen mainScreen].bounds];
    self.window.backgroundColor = [UIColor whiteColor];
    
    ViewController* VC = [[ViewController alloc]init];
    UINavigationController *nav = [[UINavigationController alloc] initWithRootViewController:VC];

    self.window.rootViewController = nav;
    [self.window makeKeyAndVisible];
    
    return YES;
}

使用 Flutter boost进行调转

- (void)btnClick:(UIButton *)btn {
    FlutterBoostRouteOptions* option = [[FlutterBoostRouteOptions alloc]init];
    option.pageName = @"/";
    [[[FlutterBoost instance] plugin].delegate pushFlutterRoute:option];
}

到此flutter boost原生交互使用结束,此时进到flutter界面导航是没有左侧的返回按钮的,这需要自己处理。

Logo

华为开发者空间,是为全球开发者打造的专属开发空间,汇聚了华为优质开发资源及工具,致力于让每一位开发者拥有一台云主机,基于华为根生态开发、创新。

更多推荐