<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/kdoc_html_views-1a98987dfd.css">
<link rel="stylesheet" href="https://csdnimg.cn/release/blogv2/dist/mdeditor/css/editerView/ck_htmledit_views-25cebea3f9.css">
<div id="content_views" class="markdown_views prism-atom-one-dark">
<svg xmlns="http://www.w3.org/2000/svg" style="display: none;">
<path stroke-linecap="round" d="M5,0 0,2.5 5,5z" id="raphael-marker-block" style="-webkit-tap-highlight-color: rgba(0, 0, 0, 0);"></path>
</svg>
<p>在 <a href="https://so.youkuaiyun.com/so/search?q=Flutter&spm=1001.2101.3001.7020" target="_blank" class="hl hl-1" data-report-click="{"spm":"1001.2101.3001.7020","dest":"https://so.youkuaiyun.com/so/search?q=Flutter&spm=1001.2101.3001.7020","extra":"{\"searchword\":\"Flutter\"}"}" data-tit="Flutter" data-pretit="flutter">Flutter</a>项目中集成完 flutter boost,并且已经使用了 flutter boost进行了路由管理,这时如果需要和iOS混合开发,这时就要到 原生端进行集成。</p>
注意:之前建的项目必须是 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
填写完后指向 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? <span class="token punctuation">{<!-- --></span>
<span class="token builtin class-name">return</span> UINavigationController.topNavigationController<span class="token punctuation">(</span><span class="token punctuation">)</span>?.navigationController
<span class="token punctuation">}</span>
///用来存返回flutter侧返回结果的表
var resultTable:Dictionary<span class="token operator"><</span>String,<span class="token punctuation">(</span><span class="token punctuation">[</span>AnyHashable:Any<span class="token punctuation">]</span>?<span class="token punctuation">)</span>-<span class="token operator">></span>Void<span class="token operator">></span> <span class="token operator">=</span> <span class="token punctuation">[</span>:<span class="token punctuation">]</span><span class="token punctuation">;</span>
func pushNativeRoute<span class="token punctuation">(</span>_ pageName: String<span class="token operator">!</span>, arguments: <span class="token punctuation">[</span>AnyHashable <span class="token builtin class-name">:</span> Any<span class="token punctuation">]</span><span class="token operator">!</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
//可以用参数来控制是push还是pop
<span class="token builtin class-name">let</span> isPresent <span class="token operator">=</span> arguments<span class="token punctuation">[</span><span class="token string">"isPresent"</span><span class="token punctuation">]</span> as? Bool ?? <span class="token boolean">false</span>
<span class="token builtin class-name">let</span> isAnimated <span class="token operator">=</span> arguments<span class="token punctuation">[</span><span class="token string">"isAnimated"</span><span class="token punctuation">]</span> as? Bool ?? <span class="token boolean">true</span>
//这里根据pageName来判断生成哪个vc,这里给个默认的了
<span class="token builtin class-name">let</span> targetViewController <span class="token operator">=</span> UIViewController<span class="token punctuation">(</span><span class="token punctuation">)</span>
// 这里也可以使用路由进行跳转
if<span class="token punctuation">(</span>isPresent<span class="token punctuation">)</span><span class="token punctuation">{<!-- --></span>
self.navigationController?.present<span class="token punctuation">(</span>targetViewController, animated: isAnimated, completion: nil<span class="token punctuation">)</span>
<span class="token punctuation">}</span>else<span class="token punctuation">{<!-- --></span>
self.navigationController?.pushViewController<span class="token punctuation">(</span>targetViewController, animated: isAnimated<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
func pushFlutterRoute<span class="token punctuation">(</span>_ options: FlutterBoostRouteOptions<span class="token operator">!</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
<span class="token builtin class-name">let</span> vc:HYFlutterViewController <span class="token operator">=</span> HYFlutterViewController<span class="token punctuation">(</span><span class="token punctuation">)</span>
vc.setName<span class="token punctuation">(</span>options.pageName, uniqueId: options.uniqueId, params: options.arguments,opaque: options.opaque<span class="token punctuation">)</span>
vc.hidesBottomBarWhenPushed <span class="token operator">=</span> <span class="token boolean">true</span>
//对这个页面设置结果
resultTable<span class="token punctuation">[</span>options.pageName<span class="token punctuation">]</span> <span class="token operator">=</span> options.onPageFinished<span class="token punctuation">;</span>
<span class="token keyword">if</span> <span class="token builtin class-name">let</span> nav <span class="token operator">=</span> navigationController <span class="token punctuation">{<!-- --></span>
nav.pushViewController<span class="token punctuation">(</span>vc, animated: <span class="token boolean">true</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
func popRoute<span class="token punctuation">(</span>_ options: FlutterBoostRouteOptions<span class="token operator">!</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
//如果当前被present的vc是container,那么就执行dismiss逻辑
<span class="token keyword">if</span> <span class="token builtin class-name">let</span> vc <span class="token operator">=</span> self.navigationController?.presentedViewController as? HYFlutterViewController, vc.uniqueIDString<span class="token punctuation">(</span><span class="token punctuation">)</span> <span class="token operator">==</span> options.uniqueId<span class="token punctuation">{<!-- --></span>
//这里分为两种情况,由于UIModalPresentationOverFullScreen下,生命周期显示会有问题
//所以需要手动调用的场景,从而使下面底部的vc调用viewAppear相关逻辑
<span class="token keyword">if</span> vc.modalPresentationStyle <span class="token operator">==</span> .overFullScreen <span class="token punctuation">{<!-- --></span>
//这里手动beginAppearanceTransition触发页面生命周期
self.navigationController?.topViewController?.beginAppearanceTransition<span class="token punctuation">(</span>true, animated: <span class="token boolean">false</span><span class="token punctuation">)</span>
vc.dismiss<span class="token punctuation">(</span>animated: <span class="token boolean">true</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
self.navigationController?.topViewController?.endAppearanceTransition<span class="token punctuation">(</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>else<span class="token punctuation">{<!-- --></span>
//正常场景,直接dismiss
vc.dismiss<span class="token punctuation">(</span>animated: true, completion: nil<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>else<span class="token punctuation">{<!-- --></span>
self.navigationController?.popViewController<span class="token punctuation">(</span>animated: <span class="token boolean">true</span><span class="token punctuation">)</span>
<span class="token punctuation">}</span>
//否则直接执行pop逻辑
//这里在pop的时候将参数带出,并且从结果表中移除
<span class="token keyword">if</span> <span class="token builtin class-name">let</span> onPageFinshed <span class="token operator">=</span> resultTable<span class="token punctuation">[</span>options.pageName<span class="token punctuation">]</span> <span class="token punctuation">{<!-- --></span>
onPageFinshed<span class="token punctuation">(</span>options.arguments<span class="token punctuation">)</span>
resultTable.removeValue<span class="token punctuation">(</span>forKey: options.pageName<span class="token punctuation">)</span>
<span class="token punctuation">}</span>
<span class="token punctuation">}</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 69
- 70
- 71
- 72
- 73
- HYFlutterViewContainer
#import <flutter_boost/FlutterBoost.h>
NS_ASSUME_NONNULL_BEGIN
@interface HYFlutterViewContainer : FBFlutterViewContainer
@end
NS_ASSUME_NONNULL_END
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
#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”];
<span class="token keyword">if</span> <span class="token punctuation">(</span><span class="token punctuation">[</span>event isEqualToString:@<span class="token string">"enablePopGesture"</span><span class="token punctuation">]</span><span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span>
// 多page情况下的侧滑动态禁用和启用事件
NSNumber *enableNum <span class="token operator">=</span> args<span class="token punctuation">[</span>@<span class="token string">"enable"</span><span class="token punctuation">]</span><span class="token punctuation">;</span>
BOOL <span class="token builtin class-name">enable</span> <span class="token operator">=</span> <span class="token punctuation">[</span>enableNum boolValue<span class="token punctuation">]</span><span class="token punctuation">;</span>
//右滑控制
// 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- 48
- 49
- 50
- 51
- 52
- 53
- 54
- 55
- 56
- 57
- 58
- 59
- 60
- 61
- 62
- 63
- 64
- 65
- 66
- 67
- 68
- 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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
#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
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
- 20
- 21
- 22
- 23
- 24
- 25
- 26
- 27
- 28
- 29
- 30
- 31
- 32
- 33
- 34
- 35
- 36
- 37
- 38
- 39
- 40
- 41
- 42
- 43
- 44
- 45
- 46
- 47
- AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { HYFlutterBoostDelegate* delegate = [[HYFlutterBoostDelegate alloc]init];
<span class="token punctuation">[</span>FlutterBoost.instance setup:application delegate:delegate callback:^<span class="token punctuation">(</span>FlutterEngine *engine<span class="token punctuation">)</span> <span class="token punctuation">{<!-- --></span> NSLog<span class="token punctuation">(</span>@<span class="token string">"FlutterBoost 开始操作"</span><span class="token punctuation">)</span><span class="token punctuation">;</span> <span class="token punctuation">}</span><span class="token punctuation">]</span><span class="token punctuation">;</span> self.window <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>UIWindow alloc<span class="token punctuation">]</span>initWithFrame:<span class="token punctuation">[</span>UIScreen mainScreen<span class="token punctuation">]</span>.bounds<span class="token punctuation">]</span><span class="token punctuation">;</span> self.window.backgroundColor <span class="token operator">=</span> <span class="token punctuation">[</span>UIColor whiteColor<span class="token punctuation">]</span><span class="token punctuation">;</span> ViewController* VC <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>ViewController alloc<span class="token punctuation">]</span>init<span class="token punctuation">]</span><span class="token punctuation">;</span> UINavigationController *nav <span class="token operator">=</span> <span class="token punctuation">[</span><span class="token punctuation">[</span>UINavigationController alloc<span class="token punctuation">]</span> initWithRootViewController:VC<span class="token punctuation">]</span><span class="token punctuation">;</span> self.window.rootViewController <span class="token operator">=</span> nav<span class="token punctuation">;</span> <span class="token punctuation">[</span>self.window makeKeyAndVisible<span class="token punctuation">]</span><span class="token punctuation">;</span> <span class="token builtin class-name">return</span> YES<span class="token punctuation">;</span>
}
- 1
- 2
- 3
- 4
- 5
- 6
- 7
- 8
- 9
- 10
- 11
- 12
- 13
- 14
- 15
- 16
- 17
- 18
- 19
使用 Flutter boost进行调转
- (void)btnClick:(UIButton *)btn {
FlutterBoostRouteOptions* option = [[FlutterBoostRouteOptions alloc]init];
option.pageName = @"/";
[[[FlutterBoost instance] plugin].delegate pushFlutterRoute:option];
}
- 1
- 2
- 3
- 4
- 5
- 6
到此flutter boost原生交互使用结束,此时进到flutter界面导航是没有左侧的返回按钮的,这需要自己处理。