iOS老司机的跨端跨平台Hybrid开发Tips

语言: CN / TW / HK

本文正在参加「金石计划 . 瓜分6万现金大奖」

前言

  • Native与H5的混合开发是目前大前端绕不开的技术点, 在实际业务场景中有各种各样的应用
  • 很多一线开发同学都会使用Hybrid混合开发中的各种技术及API, 去完成各种相互调用的需求
  • 知其然, 知其所以然. 作为一个有追求的大前端从业者, 我们一起来探究一下iOS中的Hybrid混合开发的前世今生.
  • 文章纯手打, 抛砖引玉, 如有错误还请评论区指正, 先行谢过了:)

1. 原生与前端交互

1.1 什么是JavaScriptCore?

  • JavaScriptCore 为原生编程语言 Objective-CSwift 提供调用 JavaScript 程序的动态能力,还能为 JavaScript 提供原生能力来弥补前端所缺能力。
  • 桥梁作用
  • JavaScriptCore,原本是 WebKit 中用来解释执行 JavaScript 代码的核心引擎
    • 解释执行 JavaScript 代码的引擎自 JavaScript 诞生起就有,不断演进,一直发展到现在
    • 如今苹果公司有 JavaScriptCore 引擎、谷歌有 V8 引擎
    • iOS7 之前,苹果公司没有开放 JavaScriptCore 引擎。
    • 从 iOS7 开始,苹果公司开始将 JavaScriptCore 框架引入 iOS 系统,并将其作为系统级的框架提供给开发者使用
  • JavaScriptCore 框架的框架名是 JavaScriptCore.framework

1.2 JavaScriptCore 框架的关键类分解剖析

  • JavaScriptCore 框架主要由 JSVirtualMachineJSContextJSValue 类组成。
  • JSVirturalMachine 的作用,是为 JavaScript 代码的运行提供一个虚拟机环境。
    • JSContext 是 JavaScript 运行环境的上下文,负责原生和 JavaScript 的数据传递
      • JSValueJavaScript值对象,用来记录 JavaScript 的原始值,并提供进行原生值对象转换的接口方法

image.png

1.3 JavaScript 代码的 JavaScriptCore 和原生应用是怎么交互的呢

  • JavaScriptCore 和原生应用要想交互,首先要有 JSContext

  • 除了 Block 外,我们还可以通过 JSExport 协议来实现在 JavaScript 中调用原生代码,

    • 也就是原生代码中让遵循 JSExport 协议的类,能够供 JavaScript 使用。

``` - (void)testJavaScriptCore {     // 创建JSVirtualMachine对象     JSVirtualMachine jsvm = [JSVirtualMachine new];     // 使用 jsvm的JSContext对象     JSContext ct = [[JSContext alloc] initWithVirtualMachine:jsvm];

//通过JavaScriptCore在原生代码中调用JavaScript变量     // 解析执行JavaScript脚本     [ct evaluateScript:@"var i = 1 + 2"];

// 转换"i"变量为原生对象     NSNumber *iNumber = [ct[@"i"] toNumber];     NSLog(@"var i is %@, iNumber is %@", ct[@"i"], iNumber);

// 解析执行 JavaScript脚本     [ct evaluateScript:@"function subtraction(x, y) { return x - y }"];

// 获得 subtraction 函数     JSValue *subtraction = ct[@"subtraction"];

// 传入参数执行subtraction函数     JSValue *resultValue = [subtraction callWithArguments:@[@(3), @(1)]];

// 将 subtraction 函数执行的结果转成原生NSNumber来使用     NSLog(@"function is %@, reusltValue is %@", subtraction, [resultValue toNumber]); } ``` image.png

1.4 iOS中Native和JavaScriptCore交互小结

  • 总的来说,JavaScriptCore 提供了前端与原生相互调用的接口,接口层上主要用的是 JSContextJSValue 这两个类,
  • 通过 JSValueevaluateScript 方法、Block 赋值 contextJSExport 协议导出来达到互通的效果。

2. Hybrid混合开发框架的几个里程牌

2.1 基于JavaScript和WebView的跨平台方案Cordova

  • Cordova的前身是PoneGap, 后被Apache收购, 成立Cordova项目组
  • Cordova的方案主要是通过H5来构建页面, 再将其显示在各个平台的WebView中.
  • Cordova官方图: image.png

2.1.1 Cordova的优缺点

  • Cordova的优点显而易见, 背靠Apache这样的大厂, 底层代码稳定, 文档清晰, 应用广泛.
  • 但是它默认是不能调用Native的一些服务的(如相机、蓝牙等硬件), 所以需要通过JavaScript进行桥接调用Native的一些API来完成某些基于硬件的功能.
  • 本身的用户体验、性能相对Native控件并不是太流畅, Native更新迭代的过程中容易产生很多适配问题.

2.2 久经考验的React Native

  • React Native是Facebook在2015年4月开源出来的跨平台开发框架, 是Facebook基于早先开源的JS框架React在原生移动应用平台的衍生应用.
  • React Native使用JS语言, 类似于H5的JSX, 以及CSS来开发移动App, 降低了使用React框架的H5前端同学的学习成本.
  • 在保留基本渲染能力的基础上, 用原生自带的UI组件实现核心渲染引擎, 从而保证了良好的渲染效果.
  • 但是, 由于React Native的本质是通过JavaScript VM调用原生接口, 相对Native组件通信较低效, 而且RN框架本身不负责渲染, 是间接通过原生进行渲染的.(参考大厂Airbnb由RN转向Native.)

2.3 Google主推的跨平台解决方案Flutter

  • Flutter使用Skia渲染引擎, 直接通过CPU、GPU进行图形绘制, 不需要依赖任何Native控件.
  • Android操作系统中, 我们编写的Native控件实际上也是依赖于Skia进行绘制渲染, 所以Flutter在某些Android小K做系统上, 甚至还要高于安卓原生(因为安卓原生中的Skia必须随着操作系统进行更新, 二Flutter SDK中总是保持最新的Skia引擎).
  • 而类似于React Native框架, 必须通过桥接操作先转成Native控件进行调用, 之后再进行渲染. image.png

3. 一些小结

  • 大前端中主流的3种跨平台框架各有利弊, 选取哪个方案, 还是要由实际业务场景及项目具体情况决定.
  • 就像我们讨论OOP POP FunctionalProgramming究竟是哪个好?
  • 最后还是MOP(Market Oriented Programming), 市场和具体业务情况决定了我们的技术选型, 应避免一味的炫技. 毕竟, 技术的成长和业务的发展是相辅相成的双生:)

发文不易, 喜欢点赞的人更有好运气👍 :), 定期更新+关注不迷路~

ps:欢迎加入笔者18年建立的研究iOS审核及前沿技术的三千人扣群:662339934,坑位有限,备注“掘金网友”可被群管通过~

本文正在参加「金石计划 . 瓜分6万现金大奖」