以前搞的Flutter版工具链已经弄完了,感兴趣的朋友能够围观下,Android版本dio库(v2.0.14)发送网络请求总是报错,去官方提了issue还没回,因而今天搞一下把Flutter模块接入到已有项目中。android
首先Flutter官方已经出了wiki,教你们怎么接入。懒得看官方原文的能够看看这个简易版快速集成,先来看看效果。ios
通常用Flutter
或者React Native
的团队大部分缘由都是由于须要跨平台,因此在已有项目目录的上一级建立Flutter
模块,譬如你的工做目录在some/path/MyApp
,那么你须要在some/path
下执行,这样Flutter
能够单独交给一个虚拟团队维护,各自独立。git
$ cd some/path/ $ flutter create -t module my_flutter
文件结构以下:github
some/path/ my_flutter/ lib/main.dart .ios/ MyApp/ MyApp.xcodeproj Podfile MyApp/ AppDelegate.h AppDelegate.m (or swift)
没用过Cocoapods
的童鞋能够google
搜一下,以前写过不少Cocoapods
的文章因为博客主机商跑路都没了,说多了都是泪swift
1.在Podfile文件加入如下代码:xcode
flutter_application_path = '../my_flutter/' eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
注意my_flutter
的路径,由于咱们是以xcodeproj
文件的上一级建立的,因此须要加../,这个和React Native
引入依赖路径是同样的,都须要注意这个问题。bash
2.执行pod install网络
注:若是报错app
[!] InvalidPodfilefile: No such file or directory @ rb_sysopen - ./my_flutter/.ios/Flutter/podhelper.rb.ide
须要在my_flutter
文件夹下执行如下flutter run
,把.ios
和.android
等flutter
配置生成出来。
3.禁用bitcode,设置环境变量
找到你的target
,Build Settings->Build Options->Enable Bitcode
设置为NO
,另外在Preprocessor Macros
添加FLUTTER_BUILD_MODE=Debug
和FLUTTER_BUILD_MODE=Release
,若是还有其余环境须要根据状况选择Debug
或Release
。
4.添加run script
找到你的target
,Build Phases -> + -> New Run Script Phase
,而且在bash
或zsh
配置FLUTTER_ROOT
,不然打包会出错找不到flutter
。涉及多人开发还须要安装路径位置,不然团队小伙伴每一个人的路径不同。
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
注:把这个script放到Target Dependencies phasescript的后面。
5.添加assets资源
官网说须要添加Flutter.framework
资源,可是这个Cocoapods
已经帮忙引入了,因此就不须要了,若是没有被引入进去那就手动引入下。这里只须要添加flutter_assets
就好了,记得选Creat folder references
引入方式。Flutter
1.0.0版本路径是my_flutter->build->flutter_assets
6.修改AppDelegate
Objective-C:
AppDelegate.h #import <UIKit/UIKit.h> #import <Flutter/Flutter.h> @interface AppDelegate : FlutterAppDelegate @property (nonatomic,strong) FlutterEngine *flutterEngine; @end AppDelegate.m #import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins #include "AppDelegate.h" @implementation AppDelegate // This override can be omitted if you do not have any Flutter Plugins. - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil]; [self.flutterEngine runWithEntrypoint:nil]; [GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine]; return [super application:application didFinishLaunchingWithOptions:launchOptions]; } @end
Swift:
AppDelegate.swift import UIKit import Flutter import FlutterPluginRegistrant // Only if you have Flutter Plugins. @UIApplicationMain class AppDelegate: FlutterAppDelegate { var flutterEngine : FlutterEngine?; // Only if you have Flutter plugins. override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { self.flutterEngine = FlutterEngine(name: "io.flutter", project: nil); self.flutterEngine?.run(withEntrypoint: nil); GeneratedPluginRegistrant.register(with: self.flutterEngine); return super.application(application, didFinishLaunchingWithOptions: launchOptions); } }
到这里,咱们的Flutter就算已经引入工程了
Objective-C:
ViewController.m #import <Flutter/Flutter.h> #import "AppDelegate.h" #import "ViewController.h" @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom]; [button addTarget:self action:@selector(handleButtonAction) forControlEvents:UIControlEventTouchUpInside]; [button setTitle:@"Press me" forState:UIControlStateNormal]; [button setBackgroundColor:[UIColor blueColor]]; button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0); [self.view addSubview:button]; } - (void)handleButtonAction { FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine]; FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil]; [self presentViewController:flutterViewController animated:false completion:nil]; } @end
Swift:
ViewController.swift import UIKit import Flutter class ViewController: UIViewController { override func viewDidLoad() { super.viewDidLoad() let button = UIButton(type:UIButtonType.custom) button.addTarget(self, action: #selector(handleButtonAction), for: .touchUpInside) button.setTitle("Press me", for: UIControlState.normal) button.frame = CGRect(x: 80.0, y: 210.0, width: 160.0, height: 40.0) button.backgroundColor = UIColor.blue self.view.addSubview(button) } @objc func handleButtonAction() { let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine; let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!; self.present(flutterViewController, animated: false, completion: nil) } }
剩下的就是写Flutter
页面逻辑了以及Flutter
模块须要调用Native API
(后面专门写一篇文章)。
写完Flutter
页面,若是要跳转到指定页面使用Flutter
的路由就能够了
Objective-C:
[flutterViewController setInitialRoute:@"route1"];
Swift:
flutterViewController.setInitialRoute("route1")
在my_flutter
手动flutter run
一下,或者直接开启热加载,而后就能够在原有的iOS
项目中用Xcoderun
起来了。
$ flutter attach --isolate-filter='debug' Waiting for a connection from Flutter... Done. Syncing files to device... 1.1s 🔥 To hot reload changes while running, press "r". To hot restart (and rebuild state), press "R". An Observatory debugger and profiler is available at: http://127.0.0.1:43343/ For a more detailed help message, press "h". To detach, press "d"; to quit, press "q". Connected view: debug isolate (isolates/642101161)
5、发布
执行flutter build ios
以建立release
版本(flutter build
默认为--release
)