Flutter 混合开发系列 包含如下:

  • 嵌入原生View-Android
  • 嵌入原生View-iOS
  • 与原生通信-MethodChannel
  • 与原生通信-BasicMessageChannel
  • 与原生通信-EventChannel
  • 添加 Flutter 到 Android Activity
  • 添加 Flutter 到 Android Fragment
  • 添加 Flutter 到 iOS

每个工作日分享一篇,欢迎关注、点赞及转发。

Flutter 可以作为 frameworks 添加到 iOS 项目,iOS项目引入Flutter module需要安装Xcode,另外Flutter支持iOS8及以上。

创建 Flutter module

由于 Xcode 无法像 Android Studio 一样安装插件,因此只能通过命令创建 Flutter module,打开终端,输入如下:

cd ios 项目根目录
flutter create --template module my_flutter

执行完毕后,Flutter module将会创建在 ios项目/my_flutter目录下,目录结构如图:

.ios 是隐藏目录,可以单独运行Flutter module,测试此模块的功能,iOS代码添加到现有应用程序的项目或插件中,而不是添加到模块的.ios /目录中。

由于.ios /目录是自动生成的,因此请勿对其进行源代码控制。在新机器上构建模块之前,请先在my_flutter目录中运行flutter pub get来重新生成.ios /目录,然后再使用Flutter模块构建iOS项目。

将Flutter模块嵌入到现有应用程序中

将Flutter模块嵌入到现有iOS应用程序中有两种方式:

  • 使用CocoaPods和已安装的Flutter SDK(推荐)。
  • 为Flutter引擎,已编译的Dart代码和所有Flutter插件创建 frameworks。手动嵌入 frameworks,并在Xcode中更新现有应用程序的构建设置。

应用程序无法在 Release 模式下的模拟器上运行,因为Flutter尚不支持为Dart代码提前输出x86 / x86_64二进制(AOT)二进制文件。在模拟器或真实设备上以调试模式运行,而在真实设备上以Release模式运行。

下面的两种方式是将 Release frameworks 添加到 iOS 应用程序,因此编译的时候设备不能选择模拟器,否则编译失败。

编译成功:

选择模拟器编译失败:

使用CocoaPods和已安装的Flutter SDK

此方法需要所有的相关开发的人员安装 Flutter 环境。

假设现有应用程序和Flutter模块位于同级目录中。如果您使用其他目录结构,则可能需要调整相对路径,目录如下:

修改iOS应用程序中 Podfile 文件,如果没有则手动创建,内容如下:

flutter_application_path = '../my_flutter'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb') target 'My App' do
install_all_flutter_pods(flutter_application_path)
end

CocoaPods 相关请参考官网

执行 pod install 命令:

当在my_flutter / pubspec.yaml中更改Flutter插件的依赖性或者第一次运行时,请在Flutter模块目录中运行flutter pub get来刷新podhelper.rb脚本读取的插件列表。然后,从应用程序目录再次运行pod install。

podhelper.rb脚本将插件Flutter.framework和App.framework嵌入到项目中。

Xcode 打开 My App.xcworkspace,如果已经打开则需要关闭重新打开,使用 ⌘B 编译项目,编译成功。

在Xcode中嵌入 Flutter Frameworks

通过命令生成必要的 Frameworks,并通过手动编辑现有的Xcode项目将它们嵌入到应用程序中。如果团队成员无法在本地安装Flutter SDK和CocoaPods,或者您不想在现有应用程序中将CocoaPods用作依赖项管理器,则可以使用此方式。每次在Flutter模块中进行代码更改时,都必须运行 flutter build ios

运行如下命令生成 Frameworks:

flutter build ios-framework --output=./Flutter/

执行完毕后在对应的目录下生成相关编译产物:

frameworks 已经生成,将 frameworks 链接到 iOS 应用程序有很多中方法,下面介绍一种, 打开 Xcode,

App.frameworkFlutter.framework 拖入Build Settings > Build Phases > Link Binary With Libraries

此时在项目的左侧增加 Frameworks 目录:

Build Settings -> Search Paths -> Framework Search Paths 中添加 ${PODS_ROOT}/../my_flutter/Flutter/Release

使用 ⌘B 编译项目,编译成功。

创建 FlutterEngine 和 FlutterViewController

将 Flutter 页面嵌入 iOS 应用程序需要创建 FlutterEngine(Flutter 引擎) 和 FlutterViewController,FlutterEngine 是Dart VM和Flutter运行时的 host,FlutterViewController 附着于 FlutterEngine,作用是通信和显示 Flutter UI。

创建 FlutterEngine:

import UIKit
import Flutter @UIApplicationMain
class AppDelegate: FlutterAppDelegate {
lazy var flutterEngine = FlutterEngine(name: "my flutter engine") override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool { flutterEngine.run(); return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}

添加一个按钮,跳转到 Flutter 页面:

import UIKit
import Flutter class ViewController: UIViewController { override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type:UIButton.ButtonType.custom)
button.addTarget(self, action: #selector(showFlutter), for: .touchUpInside)
button.setTitle("显示 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)
} }

上面的代码使用了缓存 FlutterEngine,当然这也是推荐的一种方式。

还有一种方式是是使用隐含的FlutterEngine,使用隐含的FlutterEngine会明显增加显示Flutter UI的时间,通常不建议这样做,如果很少显示 Flutter 屏幕,没有好的方法来确定何时启动Dart VM以及何时Flutter不需要在视图控制器之间保持状态,则这可能很有用。

func showFlutter() {
let flutterViewController = FlutterViewController(project: nil, nibName: nil, bundle: nil)
present(flutterViewController, animated: true, completion: nil)
}

指定入口点

默认情况下 FlutterEngine 加载 lib/main.dart 文件中的 main() 方法,也可以指定其他文件的方法:

flutterEngine.run(withEntrypoint: "newEntrypoint", libraryURI: "main.dart")

初始化路由

从Flutter 1.22版开始,可以指定路由

let flutterEngine = FlutterEngine()
flutterEngine.run(
withEntrypoint: FlutterDefaultDartEntrypoint, initialRoute: "/one_page")

交流

老孟Flutter博客(330个控件用法+实战入门系列文章):http://laomengit.com

欢迎加入Flutter交流群(微信:laomengit)、关注公众号【老孟Flutter】:

【Flutter 混合开发】添加 Flutter 到 iOS的更多相关文章

  1. 【Flutter 混合开发】添加 Flutter 到 Android Activity

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  2. 【Flutter 混合开发】添加 Flutter 到 Android Fragment

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  3. 【Flutter 混合开发】嵌入原生View-Android

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-IOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  4. 【Flutter 混合开发】嵌入原生View-iOS

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  5. 【Flutter 混合开发】与原生通信-MethodChannel

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  6. 【Flutter 混合开发】与原生通信-BasicMessageChannel

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  7. 【Flutter 混合开发】与原生通信-EventChannel

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  8. Flutter混合开发:Android接入Flutter

    Flutter Google推出已经已经一年多了,单个 Flutter 项目的开发流程已经很成熟了.对与个人开发者来说使用 Flutter 开发一个跨平台的App挺有意思.但是对于现有的项目改造来说还 ...

  9. flutter 混合开发

    flutter 混合开发 https://github.com/flutter/flutter/wiki/Add-Flutter-to-existing-apps https://flutter.de ...

随机推荐

  1. Object.defineProperty和proxy

    Object.defineProperty问题 Object.defineProperty() 无法监控到数组下标的变化.vue只能通过以下几种方法来监听 pop() shift() unshift( ...

  2. MySQL 5.7主从复制

    简介 主从复制是利用MySQL复制机制将数据复制到另外一台或多台MySQL服务器上,被复制的服务器称为主服务器,复制的服务器称为从服务器.一般是一主多从.主从复制的好处主要是数据备份.负载均衡(读写分 ...

  3. 晚间测试3 B. 单(single)

    题目描述 单车联通大街小巷.这就是出题人没有写题目背景的原因. 对于一棵树,认为每条边长度为 \(1\),每个点有一个权值\(a[i]\).\(dis(u,v)\)为点\(u\)到\(v\)的最短路径 ...

  4. java安全编码指南之:方法编写指南

    目录 简介 不要在构造函数中调用可以被重写的方法 不要在clone()方法中调用可重写的方法 重写equals()方法 hashCode和equals compareTo方法的实现 简介 java程序 ...

  5. 077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象

    077 01 Android 零基础入门 02 Java面向对象 01 Java面向对象基础 01 初识面向对象 02 类和对象 本文知识点:类和对象 说明:因为时间紧张,本人写博客过程中只是对知识点 ...

  6. 2020 CSP-J 初赛答案及解析

    部分咕咕咕的明天一定 单项选择 A A D 解析 : 与z的都是假 C 解析 : $ \frac{2048\times1024\times32}{8\times1024\times1024}=8$ C ...

  7. 微信小程序实时将less编译为wxss

    1.npm或者yarn全局安装wxss-cli npm install -g wxss-cli 2.运行waxes-cli命令(mp_wx为小程序目录) wxss ./mp_wx 实时监听mp_wx目 ...

  8. CentOS 7系统常见快捷键操作方式

    快捷键操作方式 Linux系统中一些常见的快捷方式,可有效提高操作效率,在某些时刻也能避免操作失误带来的问题. 最有用的快捷键 序号 快捷键 官方说明 掌握程度 01 Tab 命令或路径等的补全键 移 ...

  9. centos7安装redis6

    wget http://download.redis.io/releases/redis-6.0.6.tar.gz?_ga=2.104030464.1049731693.1595900008-1330 ...

  10. php长时间的脚本,报502

    php-fpm超时时间设置request_terminate_timeout分析原创loophome 最后发布于2017-11-22 16:17:59 阅读数 21201 收藏展开今天发现了一个很神奇 ...