Flutter iOS 集成使用 fluter boost

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

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

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

  • 在原生项目的 Podfile文件中添加如下代码
dart 复制代码
# 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

bash 复制代码
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
bash 复制代码
#import <flutter_boost/FlutterBoost.h>

NS_ASSUME_NONNULL_BEGIN

@interface HYFlutterViewContainer : FBFlutterViewContainer

@end

NS_ASSUME_NONNULL_END
bash 复制代码
#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
bash 复制代码
#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
bash 复制代码
#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
bash 复制代码
- (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进行调转

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

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

相关推荐
野盒子1 小时前
前端面试题 微信小程序兼容性问题与组件适配策略
前端·javascript·面试·微信小程序·小程序·cocoa
无知的前端2 小时前
Flutter开发,GetX框架路由相关详细示例
android·flutter·ios
大熊猫侯佩3 小时前
iOS 18 中全新 SwiftData 重装升级,其中一个功能保证你们“爱不释手”
数据库·ios·swift
大熊猫侯佩3 小时前
SwiftUI 6.0(iOS 18)新容器视图修改器漫谈
ios·swiftui·wwdc
Digitally4 小时前
如何将 iPhone 中的短信导出为 PDF
ios·pdf·iphone
icc_tips15 小时前
Flutter 的Async/Await 日常使用
flutter
造梦师16 小时前
flutter基础面试知识汇总(二)
flutter
vvilkim16 小时前
Flutter 核心概念:深入理解 StatelessWidget 与 StatefulWidget
开发语言·javascript·flutter
sunly_16 小时前
Flutter:导航背景固定在顶部,下拉分页布局
开发语言·javascript·flutter
明似水16 小时前
使用 Melos 高效管理 Flutter/Dart Monorepo 项目
flutter