1. 前言

我们给 Android 接入 Flutter Boost 之后,现在我们来看看如何给 iOS 工程(OC)接入 Flutter Boost。

本文将简单梳理一下 iOS 工程接入的 Flutter Boost 的流程,以作为前文的补充。

参见前文:Flutter Boost 混合开发实践与源码解析(以 Android 为例),Flutter Module 也依旧用前文生成的,目录结构依旧如前文所述,不再赘述。

2. 接入

2.1 工程准备

准备一个配有 Cocoapods 的空白工程,在 Podfile 中配置我们之前准备好的 Flutter Module 作为依赖:

  1. flutter_application_path = '../flutter_module'
  2. load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
  3. target 'FlutterHybridiOS' do
  4. install_all_flutter_pods(flutter_application_path)
  5. end

接着在工程根目录下运行 pod install ,即可集成上 Flutter Module。看到我们的 Pods 中多了以下几个模块,即说明集成成功。

image.png

如不了解 Cocoapods,请参见 CocoaPods 使用指南

2.2 实现路由类

这一块直接参照 Flutter Boost 官方提供的 example 就好了:https://github.com/alibaba/flutter_boost/blob/master/example/ios/Runner/PlatformRouterImp.h

PlatformRouterImp.h:

  1. #import <Foundation/Foundation.h>
  2. #import <UIKit/UIKit.h>
  3. #import <flutter_boost/FlutterBoost.h>
  4. NS_ASSUME_NONNULL_BEGIN
  5. @protocol FLBPlatform;
  6. /**
  7. * 实现平台侧的页面打开和关闭,不建议直接使用用于页面打开,建议使用FlutterBoostPlugin中的open和close方法来打开或关闭页面;
  8. * FlutterBoostPlugin带有页面返回数据的能力
  9. */
  10. @interface PlatformRouterImp : NSObject<FLBPlatform>
  11. @property (nonatomic,strong) UINavigationController *navigationController;
  12. @end
  13. NS_ASSUME_NONNULL_END

PlatformRouterImp.m:

  1. #import "PlatformRouterImp.h"
  2. #import <flutter_boost/FlutterBoost.h>
  3. @interface PlatformRouterImp()
  4. @end
  5. @implementation PlatformRouterImp
  6. #pragma mark - Boost 1.5
  7. - (void)open:(NSString *)name
  8. urlParams:(NSDictionary *)params
  9. exts:(NSDictionary *)exts
  10. completion:(void (^)(BOOL))completion
  11. {
  12. BOOL animated = [exts[@"animated"] boolValue];
  13. FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
  14. [vc setName:name params:params];
  15. [self.navigationController pushViewController:vc animated:animated];
  16. if(completion) completion(YES);
  17. }
  18. - (void)present:(NSString *)name
  19. urlParams:(NSDictionary *)params
  20. exts:(NSDictionary *)exts
  21. completion:(void (^)(BOOL))completion
  22. {
  23. BOOL animated = [exts[@"animated"] boolValue];
  24. FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
  25. [vc setName:name params:params];
  26. [self.navigationController presentViewController:vc animated:animated completion:^{
  27. if(completion) completion(YES);
  28. }];
  29. }
  30. - (void)close:(NSString *)uid
  31. result:(NSDictionary *)result
  32. exts:(NSDictionary *)exts
  33. completion:(void (^)(BOOL))completion
  34. {
  35. BOOL animated = [exts[@"animated"] boolValue];
  36. animated = YES;
  37. FLBFlutterViewContainer *vc = (id)self.navigationController.presentedViewController;
  38. if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
  39. [vc dismissViewControllerAnimated:animated completion:^{}];
  40. }else{
  41. [self.navigationController popViewControllerAnimated:animated];
  42. }
  43. }
  44. @end

可以看到,Flutter Boost 支持常规 push,也支持打开模态弹窗,也支持手动 pop。

2.3 绑定路由管理

AppDelegate.h:

  1. #import <UIKit/UIKit.h>
  2. #import <flutter_boost/FlutterBoost.h>
  3. @interface AppDelegate : UIResponder <UIApplicationDelegate>
  4. @property (nullable, nonatomic, strong) UIWindow *window;
  5. @end

AppDelegate.m:

  1. #import "AppDelegate.h"
  2. #import "PlatformRouterImp.h"
  3. #import <flutter_boost/FlutterBoost.h>
  4. @interface AppDelegate ()
  5. @end
  6. @implementation AppDelegate
  7. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  8. PlatformRouterImp *router = [PlatformRouterImp new];
  9. [FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
  10. onStart:^(FlutterEngine *engine) {
  11. }];
  12. UITabBarController *tabVC = [[UITabBarController alloc] init];
  13. UINavigationController *rvc = [[UINavigationController alloc] initWithRootViewController:tabVC];
  14. router.navigationController = rvc;
  15. return YES;
  16. }

3. 使用

  1. - (void)openClick:(UIButton *)button
  2. {
  3. [FlutterBoostPlugin open:@"first" urlParams:@{kPageCallBackId:@"MycallbackId#1"} exts:@{@"animated":@(YES)} onPageFinished:^(NSDictionary *result) {
  4. NSLog(@"call me when page finished, and your result is:%@", result);
  5. } completion:^(BOOL f) {
  6. NSLog(@"page is opened");
  7. }];
  8. }
  9. - (void)openPresentClick:(UIButton *)button
  10. {
  11. [FlutterBoostPlugin open:@"second" urlParams:@{@"present":@(YES),kPageCallBackId:@"MycallbackId#2"} exts:@{@"animated":@(YES)} onPageFinished:^(NSDictionary *result) {
  12. NSLog(@"call me when page finished, and your result is:%@", result);
  13. } completion:^(BOOL f) {
  14. NSLog(@"page is presented");
  15. }];
  16. }

同样的,这里可在 Native 端用两种不同的方式去打开我们在 Flutter Module 中注册好的路由名。

至此,我们成功在 iOS 工程中接入了 Flutter Boost,那就开启我们的混编之旅吧~