在 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界面导航是没有左侧的返回按钮的,这需要自己处理。