在 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 frameworksuse_frameworks!# Pods for FlutterListinstall_all_flutter_pods(flutter_application_path)pod 'Masonry', '1.0.2'endpost_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_boostclass 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还是poplet isPresent = arguments["isPresent"] as? Bool ?? falselet 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{//正常场景,直接dismissvc.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@endNS_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界面导航是没有左侧的返回按钮的,这需要自己处理。