iOS现有项目集成Flutter与相互交互

1.iOS集成Flutter

1.1创建项目

创建原生项目"iOS_demo",创建Flutter项目"flutter_lab",两个项目在同一级目录, 在flutter_lab项目里找到lib文件夹,添加dart代码,如图:

目录结构

1.2使用CocoPods集成

"iOS_demo"添加PodFile文件,命令:cd iOS_demo path -> touch Podfile
打开新创建的Podfile文件,添加代码

flutter_application_path = '../flutter_lab'  //这里是flutter项目名
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')

target 'iOS_demo' do
  install_all_flutter_pods(flutter_application_path)
end

命令: pod install, iOS集成Flutter完成

2.iOS调起Flutter

2.1 AppDelegate配置,注册FlutterEngine,代码如下:
import UIKit
import Flutter
import FlutterPluginRegistrant

@main
class AppDelegate: UIResponder, UIApplicationDelegate {
    lazy var flutterEngine = FlutterEngine(name: "my flutter engine")
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        // Override point for customization after application launch.
        GeneratedPluginRegistrant.register(with: self.flutterEngine);
        flutterEngine.run()
        return true
    }
}
2.2 使用 FlutterEngine 展示 FlutterViewController,代码如下:
import UIKit
import Flutter

class ViewController: UIViewController {
  override func viewDidLoad() {
    super.viewDidLoad()

    // Make a button to call the showFlutter function when pressed.
    let button = UIButton(type:UIButton.ButtonType.custom)
    button.addTarget(self, action: #selector(showFlutter), for: .touchUpInside)
    button.setTitle("Show Flutter!", for: UIControl.State.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 showFlutter() {
    let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
    let flutterViewController =
        FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)
    present(flutterViewController, animated: true, completion: nil)
  }
}

以上默认执行flutter的main函数, 只能实现调起单一路由(控制器),实际操作中,一个iOS原生控制器会根据不同的事件调起不同的路由, 操作如下,首先需要更改2.2代码:

@objc func showFlutter() {
   let flutterViewController = FlutterViewController(project: nil, initialRoute: "home", nibName: nil, bundle: nil) // 这里initialRoute要与Flutter项目中的main.dart设置的名称一致, 跳转到homeVC路由
   self.modalPresentationStyle = .fullScreen
   self.navigationController?.setNavigationBarHidden(true, animated: true)
   self.navigationController?.pushViewController(flutterViewController, animated: true)        
}

main.dart代码如下:

void main() {
  // 获取原生跳转的路由,根据路由显示对应的界面,ui.window.defaultRouteName就是上面设置的 “home”路由标识
  runApp(run(ui.window.defaultRouteName));
}

//根据路由标识返回对应的Widget,这里需要注意的是如果是单独的界面,必须使用MaterialApp包裹住,不然跳转过来后显示不了当前ui
Widget run(String name){
  switch (name) {
    case "test":
      return TestVC();
      break;
    case "home":
      return HomeVC();
      break;
    case "myApp":
      return MyApp();
      break;
  }
  return Center(
    child: Text('Unknown route: $name'),
  );
}

3.iOS与Flutter相互传值

3.1.iOS传值到Flutter

iOS代码:
按钮点击方法showFlutter()的跳转加FlutterEventChannel

@objc func showFlutter() {
//   push代码...
let evenChannel1 = FlutterEventChannel.init(name: "com.nativeToFlutter", binaryMessenger: flutterViewController as! FlutterBinaryMessenger)
evenChannel1.setStreamHandler(self)
}

实现代理方法,该代理方法,只有Flutter项目做了监听才可以触发:

func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
        print("push传值代理方法")
        events(["key": "push传值", "state": "0"])
        return nil
    }
    
func onCancel(withArguments arguments: Any?) -> FlutterError? {  
      return nil
 }

Flutter中的HomeVC代码:

class _HomeVCState extends State<HomeVC> {
  //注意这里的com.nativeToFlutter一定要与原生的名称相同,不然没办法通信
  static const eventChannel = EventChannel('com.nativeToFlutter');
  @override
  void initState() {
    // TODO: implement initState
    super.initState();
    eventChannel.receiveBroadcastStream().listen(_getData,onError: _getError);
  }
  //获得到传值(["key": "push传值", "state": "0"])
  void _getData(dynamic data) {
    print("传值${data}");
  }
//获取到错误
  void _getError(Object err) {

  }
3.1.Flutter传值到iOS

iOS代码:
按钮点击方法showFlutter()的跳转加FlutterEventChannel

@objc func showFlutter() {
//   push代码...
let presentChannel:FlutterMethodChannel = FlutterMethodChannel.init(name: "sf.flutter.io/sf_present", binaryMessenger: flutterViewController as! FlutterBinaryMessenger)
weak var weakSelf = self
// 添加监听回调
presentChannel.setMethodCallHandler { (call, result) in
  print(call.method)
   // 当flutter调用了原生方法后,此回调会调用
   // call.method 为方法名,call对象里面还有参数属性
  if call.method == "getNativeResult" {
      let dict:[String : Any] = call.arguments as! [String : Any]
      print(dict["key"] ?? "")
      weakSelf?.navigationController?.popViewController(animated: true)
     }
  }
}

Flutter中的HomeVC代码:

// 任意事件返回到原生,同时传值到原生
Future<void> invokeNativeGetResult() async {
    try {
      // 调用原生方法并传参,以及等待原生返回结果数据,getNativeResult是方法名,{"key": "value"}是参数
      var result = await platform.invokeListMethod('getNativeResult', {"key": "参数1"});
    } catch (e) {}
  }
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,456评论 5 477
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,370评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,337评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,583评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,596评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,572评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,936评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,595评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,850评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,601评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,685评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,371评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,951评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,934评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,167评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 43,636评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,411评论 2 342

推荐阅读更多精彩内容