前沿
由於我司已經有自己的App,flutter屬於技術引進的一部分,也不太可能重新啟動一個項目,因此目前我們是將flutter模塊形式注入我們的App之中。即:將flutter模塊集成到現在有iOS工程之中。
目錄
- 創建flutter模塊工程
- 使用pod 將flutter 模塊工程添加到現有工程之中
- code 執行flutter 工程
- 運行熱更新
1. 創建flutter模塊工程
我這里是使用Android Studio 創建flutter工程,如下:
當然也可以使用flutter命令行進行創建,命令如下:
$ cd some/path/
$ flutter create -t module my_flutter
工程結構 和我們的iOS 工程保持相對目錄,結構如下:
some/path/ my_flutter/ lib/main.dart .ios/ MyApp/ MyApp/ AppDelegate.h AppDelegate.m (or swift) :
2. 使用pod 將flutter 模塊工程添加到現有工程之中
2.1 podfile 文件之中引入 flutter模塊工程
####Flutter### flutter_application_path = '../my_flutter' //目錄結構按照具體我們存儲的路徑進行 eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
2.2 然后執行pod install
2.3 ENABLE_BITCODE 設置為NO
2.4 Build Phares 添加 以下腳本(+ 號添加一個新的腳本,然后復制下面的內容)
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build "$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
執行編譯即可
最新版本集成 (最新版本已經優化了很多東西,不需要配置sh)
####Flutter### flutter_application_path = 'somepath/flutter_rokid' load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'App' do
install_all_flutter_pods(flutter_application_path)
....
end
3.code 執行flutter 工程
1. AppDelete.h 配置
import FlutterPluginRegistrant // Only if you have Flutter Plugins. @UIApplicationMain class AppDelegate: FlutterAppDelegate {
...
self.flutterEngine = FlutterEngine(name: "xxx.flutter", project: nil);
self.flutterEngine?.run(withEntrypoint: nil);
GeneratedPluginRegistrant.register(with: self.flutterEngine);
...
}
2. 業務方調用
import Foundation import Flutter class RKFlutterDemo : UIViewController { override func viewDidLoad() { title = "flutter " var 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) button = UIButton(type:UIButtonType.custom) button.addTarget(self, action: #selector(handleButtonAction1), for: .touchUpInside) button.setTitle("Press me v1", for: UIControlState.normal) button.frame = CGRect(x: 80.0, y: 270.0, width: 160.0, height: 40.0) button.backgroundColor = UIColor.blue self.view.addSubview(button) button = UIButton(type:UIButtonType.custom) button.addTarget(self, action: #selector(handleButtonAction2), for: .touchUpInside) button.setTitle("Press me v2", for: UIControlState.normal) button.frame = CGRect(x: 80.0, y: 330.0, width: 160.0, height: 40.0) button.backgroundColor = UIColor.blue self.view.addSubview(button) }
//全局生命周期,即便是 VC 退出頁面下次打開還是會 停留在上一次操作結果(所以適合全局性頁面) @objc func handleButtonAction() { let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine; let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!; self.navigationController?.pushViewController(flutterViewController, animated: true) }
//每次都會創建實例 @objc func handleButtonAction1(){ let flutterViewController = FlutterViewController(); self.navigationController?.pushViewController(flutterViewController, animated: true) }
//如果一個模塊有多個 頁面導航,則需要設置路由進行跳轉 @objc func handleButtonAction2(){ let flutterViewController = FlutterViewController(); flutterViewController.setInitialRoute("router1") //跳轉到路由 self.navigationController?.pushViewController(flutterViewController, animated: true) } }
4. 運行熱更新
其實在我們App 集成完成之后,我們還是可以在flutter工程之中直接運行到我們自己的工程之中
4.1 使用Xcode運行我們的App Command+R 運行
4.2 cd 到 在flutter 工程下 執行命令行:
flutter attach
這樣我們直接編寫 ,然后在 命令行中 按住 r 就可以 直接更新 App 中的頁面了
備注:在3的打開方式之中 只能以下模式的頁面可以更新
@objc func handleButtonAction() {
let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine; let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!; self.navigationController?.pushViewController(flutterViewController, animated: true) }
參考文獻