以前搞的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
)