2020最新flutter模块集成到原生iOS项目(一)
2020-01-31 本文已影响0人
WinJayQ
一、项目背景
* 公司的App主要面向政企事业单位,用来协同办公,其中有个动态模块(类似朋友圈与博客)
* 领导安排了一位同事将原生的动态用flutter重新写了一遍,主要是UI方面
* 大部分业务使用Channel机制与原生通信,并使用路由跳转不同的原生页面
二、参考add-to-app文档
-
将Flutter module集成到iOS项目-中文文档
https://flutter.cn/docs/development/add-to-app/ios/project-setup -
在iOS应用中添加Flutter页面
https://flutter.cn/docs/development/add-to-app/ios/add-flutter-screen?tab=engine-objective-c-tab
三、集成的详细步骤
1、将Flutter SDK集成到原生项目中
1)为了将 Flutter 集成到你的既有应用里,第一步要创建一个 Flutter module
cd /Users/xxx/Documents/ProjectName (cd到项目的文件夹)
flutter create --template module flutter_module
- 我为了图方便,将flutter_module(名称自定义)目录放在了ProjectName里面,add-to-app文档推荐flutter_module与ProjectName同级
-
如下图表示创建成功:
image.png
2)使用 CocoaPods 依赖管理和已安装的 Flutter SDK 。(推荐)
在ProjectName的Podfile中添加代码
flutter_application_path = './flutter_module'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
- 注意:flutter_module名称是自定义,并且路径也是自己的真实路径 './flutter_module'是因为我的flutter_module在ProjectName里面,如果同级,则路径是'../flutter_module'
- 通过修改flutter_application_path也可以切换不同的flutter_module,方便测试,比如你还有个flutter_test,只需要修改flutter_application_path = './flutter_test',注意路径要跟你自己的一致,然后pod install就可以了
在target中添加代码
target 'ProjectName' do
install_all_flutter_pods(flutter_application_path)
end
• podhelper.rb 脚本会把你的 plugins, Flutter.framework,和 App.framework 集成到你的项目中。
pod install成功如下图:
image.png
- flutter中的依赖如果有修改的话,都需要重新执行pod install
3)工程目录中能看到如下图:
image.png- 此时在Xode中编译成功
2、在 iOS 应用中添加 Flutter 页面
1)创建一个 FlutterEngine
在 AppDelegate.h:
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
在 AppDelegate.m:
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h>
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
self.flutterEngine = [[FlutterEngine alloc] initWithName:@"my flutter engine"];
[self.flutterEngine run];
[GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
2)在你想要集成flutter的ViewController中
添加:
#import "AppDelegate.h"
- (void)viewDidLoad
{
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:@selector(showFlutter)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Show Flutter!" forState:UIControlStateNormal];
button.backgroundColor = UIColor.blueColor;
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)showFlutter {
FlutterEngine *flutterEngine =
((SCAppDelegate *)UIApplication.sharedApplication.delegate).flutterEngine;
FlutterViewController *flutterViewController =
[[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
flutterViewController.modalPresentationStyle = UIModalPresentationFullScreen;
[self presentViewController:flutterViewController animated:YES completion:nil];
}
3)编译成功,运行如下图:
WechatIMG2.jpeg
四、集成项目时遇到的问题
1、flutter中用的某些依赖可能需要科学上网工具,比如我们的flutter模块用到了FMDB
CocoaPods设置:
export http_proxy=http://xxx
export https_proxy=https://xxx
git设置:
git config --global http.proxy http://xxx
git config --global https.proxy https://xxx
-
http://xxx和https.proxy https://xxx 为你的proxy地址
比如我用蓝灯,如下图:
image.png
2、第三方库冲突
比如flutter中依赖Reachability,原生中也依赖Reachability,如果它们版本不一致,则会发生冲突,可以将flutter和原生中依赖的Reachability版本改为一致
3、路由设置不生效,一直是默认的"/"
参考https://github.com/flutter/flutter/issues/27216中的解决方法,如下:
- FlutterEngine will run before you create FlutterViewController so you cannot setInitialRoute.
- To solve, you must remove that line in AppDelegate, init FlutterViewController without FlutterEngine let flutterViewController = FlutterViewController(nibName: nil, bundle: nil), and setInitialRoute, final call flutterEngine?.run(withEntrypoint: nil).