iOS 工程实现native 跳转指定的Flutter 页面

概要

前一篇文章中我们提到,iOS跳转到Flutter工程指定页面时(多个),Flutter只有单例,设置setInitialRouter 无效,如下

  let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!
        flutterViewController.setInitialRoute("test1")

基于不是很甘心,一直想实现完美的解决方案,所以最近几天又看了下解决各方面的解决方案,最终还是有了可行方案,步骤如下

1、设置delegate 代码

这里代码 多了 ‘FlutterBasicMessageChannel’  设置,其中_kReloadChannelName要和 flutter上的代码保持一致

let _kReloadChannelName = "reload"

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate ,FlutterAppLifeCycleProvider{

    static var shared: AppDelegate?

    var window: UIWindow?

    var _lifeCycleDelegate = FlutterPluginAppLifeCycleDelegate()
    var flutterEngine : FlutterEngine!
    var  flutterViewController : RKFlutterViewController!
    var  reloadMessageChannel : FlutterBasicMessageChannel!

    func addApplicationLifeCycleDelegate(_ delegate: FlutterPlugin) {
        _lifeCycleDelegate.add(delegate)
    }

    func flutterSetup(){
        flutterEngine = FlutterEngine(name: "rokid.flutter", project: nil)
        flutterEngine.run(withEntrypoint: nil)
        //全局引擎(解决启动加载时候m,无法处理和native交互问题)
        flutterViewController = RKFlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!
        GeneratedPluginRegistrant.register(with: flutterEngine)
        //实现App 路由跳转
        reloadMessageChannel = FlutterBasicMessageChannel(name: _kReloadChannelName, binaryMessenger: flutterEngine, codec: FlutterStringCodec.sharedInstance())
    }

    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
        ...
        flutterSetup()
       ...
}    

2、iOS App 跳转指定路由

   @objc func handleButtonAction() {
         self.engine().navigationChannel.invokeMethod("setInitialRoute", arguments: "test")
        self.reloadMessageChannel().sendMessage("test")
        let flutterViewController = FlutterViewController(engine: self.engine(), nibName: nil, bundle: nil)!
        self.navigationController?.pushViewController(flutterViewController, animated: true)
    }

 func engine() -> FlutterEngine {
        return (UIApplication.shared.delegate! as! AppDelegate).flutterEngine
    }

    func reloadMessageChannel() -> FlutterBasicMessageChannel {
        return (UIApplication.shared.delegate! as! AppDelegate).reloadMessageChannel
    }

3、flutter路由代码如下

import ‘package:flutter/material.dart‘;
import ‘package:flutter/services.dart‘;
import ‘dart:ui‘ as ui;
import ‘src/pages/playground/PlaygroundPage.dart‘;

/// Channel used to let the Flutter app know to reset the app to a specific
/// route.  See the [run] method.
///
/// Note that we shouldn‘t use the `setInitialRoute` method on the system
/// navigation channel, as that never gets propagated back to Flutter after the
/// initial call.
const String _kReloadChannelName = ‘reload‘;
const BasicMessageChannel<String> _kReloadChannel =
BasicMessageChannel<String>(_kReloadChannelName, StringCodec());

void main(){
  // Start listening immediately for messages from the iOS side. ObjC calls
  // will be made to let us know when we should be changing the app state.
  _kReloadChannel.setMessageHandler(run);
  // Start off with whatever the initial route is supposed to be.
  run(ui.window.defaultRouteName);
}

Future<String> run(String name) async{
  // The platform-specific component will call [setInitialRoute] on the Flutter
  // view (or view controller for iOS) to set [ui.window.defaultRouteName].
  // We then dispatch based on the route names to show different Flutter
  // widgets.
  // Since we don‘t really care about Flutter-side navigation in this app, we‘re
  // not using a regular routes map.
  switch (name) {
    case "test":
      runApp(appRouter(title: "我是路由测试test00",));
      break;
    case "test1":
      runApp(appRouter(title: "我是路由测试test01",));
      break;
    case "test2":
      runApp(appRouter(title: "我是路由测试test02",));
      break;
    default:
      runApp(MyApp());
      break;
  }
  return ‘‘;
}

class  appRouter extends StatelessWidget {
  appRouter({this.title});

  final String title;
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: ‘Flutter rokid‘,
      debugShowCheckedModeBanner: false,// 显示和隐藏
      theme: ThemeData(
        primarySwatch: Colors.blue,
      ),
      home: PlaygroundPage(title: ‘$title‘),
    );
  }
}

class MyApp extends StatelessWidget {
  // This widget is the root of your application.
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: ‘Flutter rokid‘,
      debugShowCheckedModeBanner: false,// 显示和隐藏
      theme: ThemeData(
        // This is the theme of your application.
        //
        // Try running your application with "flutter run". You‘ll see the
        // application has a blue toolbar. Then, without quitting the app, try
        // changing the primarySwatch below to Colors.green and then invoke
        // "hot reload" (press "r" in the console where you ran "flutter run",
        // or press Run > Flutter Hot Reload in a Flutter IDE). Notice that the
        // counter didn‘t reset back to zero; the application is not restarted.
        primarySwatch: Colors.blue,
      ),
      home: PlaygroundPage(title: ‘若琪实验室‘),
      routes: <String ,WidgetBuilder>{
        "router1": (_) => new PlaygroundPage(title: "我是内部路由测试test00",),
        "router2": (_) => new PlaygroundPage(title: "我是内部路由测试test01",)
    },
    );
  }
}

思考和总结

上面代码可以实现:native -> 任意 flutter   ,但是flutter Engine是单例子,能否实现 native->flutter ->native->flutter呢?

功能和交互如何去选择呢???

参考资料

https://github.com/flutter/flutter/issues/27882

https://github.com/flutter/flutter/blob/master/dev/integration_tests/ios_add2app/ios_add2app/MainViewController.m

https://github.com/flutter/flutter/blob/master/dev/integration_tests/ios_add2app/flutterapp/lib/main.dart

原文地址:https://www.cnblogs.com/kingbo/p/11269026.html

时间: 2024-10-10 09:44:44

iOS 工程实现native 跳转指定的Flutter 页面的相关文章

silverlight 跳转指定的aspx页面

1.在xaml.cs中直接访问.并传递参数 1 System.Windows.Browser.HtmlPage.Window.Navigate(new Uri(HtmlPage.Document.DocumentUri, string.Format("ReportQuery/ReportFolder/RainReportThematicReadOnly.aspx?begintime={0}&endtime={1}&title={2}&stcd={3}&result

ios设置蓝牙,跳转到设蓝牙页面

添加框架CoreBluetooth.framewprk 在要跳转蓝牙设置界面添加类#import "CoreBluetooth/CoreBluetooth.h" 并声明代理<CBCentralManagerDelegate> 设置全局的控件@property (nonatomic, strong)CBCentralManager *cb; 在要跳转的地方写 _cb = [[CBCentralManager alloc] initWithDelegate:self queue

编译依赖于React Native0.46.4的React Native IOS工程时,出现错误“fatal error: &#39;React/RCTEventEmitter.h&#39; file not found”

我的环境: WebStorm 2017.2Build #WS-172.3317.70, built on July 14, 2017 JRE: 1.8.0_152-release-915-b5 x86_64JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Mac OS X 10.12.6 Xcode8.3.3(8E3004b) 网上搜索,可以解决我的问题的网址:https://stackoverflow.com/questions/41663002

iOS 远程推送 根据后台推送内容的不同跳转指定页面

转发自:http://www.jianshu.com/p/4531bd6e3a01 iOS 远程推送,根据后台推送内容的不同, 跳转指定页面 我目前的需求是总体分为两类: 1:私信.关注.点赞一类,只需跳转到对应的tabbar 中的某一项 2:每日精品文章项目推送,分两个子类 (1)如果当前已经打开 文章项目页面,则直接刷新,不推出新页面 (2)如果当前未打开此页面,则push出新的文章项目页面 iOS 推送情况分为 应用未启动的 情况: 打开应用 ,推送信息 会通过 - (BOOL)appli

iOS工程中的info.plist文件的完整研究

原地址:http://blog.sina.com.cn/s/blog_947c4a9f0100zf41.html 们建立一个工程后,会在Supporting files下面看到一个"工程名-Info.plist"的文件,这个是对工程做一些运行期配置的文件,很重要,不能删除. 如果你在网上下载的工程中的这个文件名只是Info.plist,那么恭喜你,这个工程太老了,是用包含SDK2.0以前的Xcode生成的,不过没关系,不影响使用. 如果你使用文本编辑器打开这个文件,你会发现这是一个XM

Mac中搭建 iOS 的 React Native 环境

手把手教你在Mac中搭建iOS的 React Native环境 http://www.cnblogs.com/damnbird/p/6074607.html 准备工作 1.你需要一台Mac电脑..(这不是废话?我所用的是Air~~穷..) 2.我所操作的电脑系统环境是 3.xcode版本:8.0正式版 必需的软件 1.Homebrew Homebrew, Mac系统的包管理器,用于安装NodeJS和一些其他必需的工具软件. 打开终端,执行 /usr/bin/ruby -e "$(curl -fs

iOS工程 与 资源文件 和 Bundle

在简单的app中,可能只会用到工程,但是项目越大,越复杂,就会需要拆分项目,将各个功能拆散到各个工程中. 可以使用worksapce来管理工程集合. 但是资源文件却不好管理,因为xcode默认只能添加自己工程内,或者子工程的资源文件到target中. 如果是平级的工程,怎么添加呢?可以使用bundle bundle虽然是os x中的资源类型,但是是兼容iOS的 我们可以先创建一个os x的bundle,然后修改其编译类型为iOS的 调整base sdk即可 然后添加资源文件(png,xib,st

集成ReactNative到现有Ios工程

前段时间刚接触了ReactNative,感觉还不错.今天心血来潮就把这边文章分享给大家,好了让我们直奔主题吧! 1.搭建ReactNative开发基础环境可以根据http://reactnative.cn/docs/0.31/getting-started.html文档来配置,安装必须的工具 2.创建一个Ios工程 TestRTC 3.进入到工程根目录下面执行安装ReactNative命令行工具  npm install -g react-native-cli 4.在工程的根目录下面创建一个Re

iOS工程中删除默认的并使用自建的ViewController后黑屏

iOS工程中删除默认的并使用自建的ViewController后黑屏 老帅(http://blog.csdn.net/shuaihj) 现象 往往我们新建一个iOS工程后,会使用自定义的ViewController,而不是其自带的.作为第一次使用iOS开发的人来说,就会遇到一个问题,app启动后黑屏,并没有如预想的那样显示自定义的View! 查看错误信息 Failed to instantiate the default view controller for UIMainStoryboardF