[17年跨领域学习]从 WKWebview 再谈混合开发

2023-08-23 0 572

译者:Lyft公用后端——玲

序言

具体来说祝贺诸位老师林慕德,17 年他们在大后端应用领域探讨点甚么呢?

那个难题我坚信许多子公司的后端相关人士单厢思索。这儿不作断言,而已带着后端老师们真真切切地一同再来深入细致地看一看混和合作开发

以后他们会特别强调其间端可视化的必要性,比如说:

POST 允诺的 Content-Type

是 application/json 却是 application/x-www-form-urlencoded,

再比如说相同后端处置布吕马的形式。

后端和应用程序可视化的必要性,即便那时的 APP 嵌入合作开发频次要比现代的 Web 中文网站多。

他们以 WKWebview 那个突破口来聊聊简而言之的混和合作开发。

注解

责任编辑中会加插大批的 iOS 标识符和词语,所以也会对 iOS 标识符艺术风格和规范化展开标示,来方便快捷后端老师介绍 iOS 的部份细节同时实现。

责任编辑更多从两个后端 iOS 应用程序的多重视角去审视混和合作开发。

如有严重错误请尖萼。

节录

很单纯的难题:他们过往的后端标识符都在甚么自然环境(罐子下)运转?

标准答案即是:浏览器(包含 PC 的各种浏览器以及手机上的浏览器)以及他们先要介绍的WebView

PC 浏览器内核的移植

对硬件原生 API 支持和 Webkit 特性都支持不够

所以许多混和合作开发解决方案的第两个点就是:

做两个增强版本的 WebView

还有人记得PhoneGap 吗?

许多他们早期的混和合作开发者基本都听过或者用过它,尤其被后端老师喜欢:

因为合作开发都是用他们擅长的后端技术合作开发 App

但是相比应用程序合作开发老师会发现它有许多诟病:

因为它不是原生和后端混合使用

在 iOS 中内部为 UIWebView

用于 iOS 网络视图加载网页

它有哪些能力?

指定两个在线网页地址,通过 NSURLRequest 类创建两个网络允诺

配合 UIWebViewloadRequst 来展开网络视图的加载

标识符实例

(void) viewDidLoad { [super viewDidLoad]; UIWebView *webview = [[UIWebViewalloc]initWithFrame:self.view.frame]; NSURL *url = [NSURL URLWithString:@”https://zhuanlan.zhihu.com/ddfe-weekly”]; NSURLRequst *request = [NSURLRequest requestWithURL:url]; [webView loadRequest:request]; [self.view addSubview:webview]; }

给后端老师的注解:

// 语法内容

*- :方法里面的加号和减号,减号一般是对象方法

viewDidLoad:视图的生命周期方法,和他们后端的 onLoad 或者 jq 里面的 ready 一样,初始化用到

NSURL – 类似他们的 Location 对象,能解析 URL

// 标识符艺术风格规范化

1、使用 4 个空格缩进,和后端合作开发规范化一样

2、方法的书写:

* – 和 (void) 有两个空格,第一行结束的 { 在当前行的末尾

PS:据说有一些子公司的 C 语言规范化是第两个大括号独占一行

UIWebView 类也支持加载 HTML 文件来同时实现远程下载或者本地离线加载

通过 UIWebViewloadHTMLString

注解:HTML 字符串引号需要转义

代理(Delegate)

在哪定义当前视图状态呢?

就是:UIWebViewDelegate

一般他们会定义 ViewController

NSData 加载

一般针对图片资源加载。

给后端老师的注解:

NSData 应用于文件读取,可以设置缓冲区

NSData 是不变缓冲区

NSMutableData 是可变缓冲区

他们看一看 UIWebView 源码里面都定义了哪些属性和方法:

注解:iOS 9.3 UIKit UIWebView.h

PS:

苹果内部对 WebView 有缓存机制,部份打开过的资源第二次访问的时候单厢尝试本地读取,但是不太稳定,关掉之后,系统会清理它。

转折点来了,那个事情也使得许多一部份老师认识到两个新词:

17年 1 月 6 号,微信团队

微信 iOS 应用程序将于 3 月 1 日逐步升级为 WKWebView 内核

WKWebView 又是甚么?

苹果支持最新的Webkit 功能

从 iOS 8 开始引入的网页浏览控件(组件)

— 高性能的 Web View 解决方案

好像是救世主?

运转消耗的内存明显减小:App 启动更快、稳定性更高

最新的 Web 标准

高达60 fps 的滚动刷新率,内置手势探测

等等

H5 和 APP 可视化形式变了?

大部份的人单厢提到 jsbridge 那个词,那真正的内涵是甚么呢?

WebViewJavascriptBridge

两个解决 OC 和 Javascript 通讯的 bridge 框架

An iOS/OSX bridge for sending messages between Obj-C and JavaScript in WKWebViews, UIWebViews & WebViews.

那原理到底是甚么?

OC 通过 WebView 的 stringByEvaluatingJavaScriptFromString来调用 js

js 调用 OC:

iOS7 引入了 JavaScriptCore,可以初始化两个 JSContext 对象,然后约定好两个方法名就好了。

一般也可以通过私有协议 Scheme,应用程序会拦截指定的协议

还有人也提到轮询,但个人感觉这种形式在一般业务场景并不是许多,除了个别特定场景,所以应用程序开销也大

注解:WebView 渲染是独立线程,所以 js 标识符实际是异步的

说了这么多,他们看一看源码(pod 版本 6.0.2):

// WebViewJavascriptBridge/WebViewJavascriptBridge.m #103 (NSString) _evaluateJavascript:(NSString)javascriptCommand { return [_webViewstringByEvaluatingJavaScriptFromString:javascriptCommand]; } // WebViewJavascriptBridge/WebViewJavascriptBridge.m #178 (BOOL)webView:(UIWebView *)webView shouldStartLoadWithRequest:(NSURLRequest *)request navigationType:(UIWebViewNavigationType) navigationType { //… }

当然细心的老师会发现,它也支持WKWebViews,他们在源码包里面也看到了文件:

他们也都知道在 H5 里面可以通过私有协议来唤起 App 以及细化到某个页面。

对于 WKWebView 呢?

最早在 stackoverflow 上有一篇 Q:

《WKWebView and NSURLProtocol not working》

里面也提到:

When using the old UIWebViewyou could catch the requests byimplementing a custom NSURLProtocol. I use this to handle requests that requires authentication.

I tried the same code and it doesnt work with the new WKWebViewbut my protocol class isnt called at all.

他们看一看回答:

WKWebView makes requests and renders content out-of-process, meaning your app does not hear the requests they make.

If you are missing a functionality, now is the time to open a bug report and/or an enhancement request with Apple.

As of iOS 10.3 SDK, WKWebView is still unable to make use of custom NSURLProtocols using public APIs.

当然后面也贴了:

Enterprising developers have found an interesting method: +[WKBrowsingContextController registerSchemeForCustomProtocol:]

It supposedly adds the provided scheme to a list of custom protocol handled schemes and should then work with NSURLProtocol.

所以大部份的混和方案都从入口 URL 拦截

这儿有几个区别

WKWebView 拦截 decidePolicyForNavigationAction 方法

他们可以在上面提到的 WebViewJavascriptBridge 的 WKWebViewJavascriptBridge.m 源码文件可以看到:

(void)webView:(WKWebView *)webView decidePolicyForNavigationAction:(WKNavigationAction *)navigationAction decisionHandler:(void (^)(WKNavigationActionPolicy))decisionHandler { //… }

UIWebView拦截 shouldStartLoadWithRequest 代理方法(那个前面也提到了)

那许多人肯定会问:切换到那个新的有什么风险吗?

看一看是否页面有适配难题

看一看 jsbridge 是否有严重错误

看一看是否有崩溃

个人觉得这些风险都是可控的,即便也会经历两个灰度的过程。部份老师也看过腾讯 Bugly 以后 1 月份发的《WKWebView 那些坑》的文章,里面也提到了几点和后端有关系的:

WKWebView 是多进程组件:Network Loading 和 UI Rendering 在其他进程执行。在一些 WebGL 渲染的复杂页面总体内存占用也不低,过大的似乎也会 crash 导致白屏

页面适配难题:比如说调用 window.innerHeight 导致页面被拉伸

视频自动播放的设置

goBack 回退上一页不触发 onload,也不会执行 js

Cookie 存储的难题:WKWebView 发起的允诺不会自动带上存储在 NSHTTPCookieStorage 罐子的 Cookie;所以存储时机会有延时。

那个就导致他们以后的后端统一登录组件换了一种方案去 hot fix,更多客源查看文末的原文链接。

他们提一下豆瓣混和合作开发框架:Rexxar (以后也邀请来Lyft分享过一次)

它主要分 3 个部份:

Rexxar Web

Rexxar IOS

Rexxar Android

责任编辑他们重点看一下 iOS 的 Rexxar Container

罐子 — 其实就是两个内置的 WebView

但是增加了原生的一些功能支持:图片缓存、Native UI 的调用等

说了这么多,他们看一看源码:

//rexxar-ios/Rexxar/Core/RXRViewController.h /**​ – 内置的 WebView。 */ @property (nonatomic, strong, readonly) UIWebView *webView;

那许多专业的人要吐槽了:

Rexxar 采用了原生的 WebView,是对 App 体积没影响

但是以后许多个 WebView 带来的内存难题也同样存在

— 那个是滴

同样的 Rexxar Container 和 Web 如何可视化呢?

前面他们介绍了 iOS 一般采用 WebViewJavascriptBridge,但它这儿不是,采用发送 HTTP 允诺(套路基本大家都是采用 iframe 加载特殊约定的 URL),然后 Container 来拦截。其实类似 Proxy,Web 发出的允诺单厢被 Proxy 处置一下。

那这儿好像没有用到 WKWebView,为甚么呢?

那个他们以后也在分享的时候请教过豆瓣的老师,他们也尝试过,即便他们前面介绍了那么多 WKWebView 的好处,大致的结论:

和他们的设计冲突

NSURLProtocol 无法截获 WKWebView 中的允诺

当然以后也听过美团大众点评的 Hybrid 方案分享,他们的流程基本也类似:

两个 URL 允诺在应用程序发起,有两个 Router 来查询本地的路由配置表(那个配置表是 App 从后台路由配置服务拉取的),根据对应的规则去跳转到 H5 却是 Native.

那如何评估两个混和应用的好坏呢,一般几个维度:

合作开发效率高

其实大家发现后面的混和方案基本的初衷都是利用前端一些优秀的地方:模块化,组件化,工程化。

当然应用程序和后端在协调合作开发的时候也有一些效率工具:比如说应用程序加载两个后端的 demo 页面,同时给后端打两个模拟器安装包,以及类似 RN 这种 debugger 调试。

缓存带来的加载快,资源文件可以本地化,所以他们可以灵活配置化的管理缓存

稳定

js 严重错误可以通过 WebView 来捕获,然后通过 App 日志发送服务端来展示

WebView 的 Crash 也可以采用 fabric 这些来收集

总结

17 年他们会放出更多跨应用领域的内容,来提升后端老师的视野,在互相协作的技术解决方案实施过程中知其所以然。

加油 & 再次林慕德。

同时感谢:Lyft iOS 高工文杰老师对 iOS 标识符的指导

扩展阅读:

marcuswestin/WebViewJavascriptBridge

Rexxar:豆瓣对混和合作开发的思索

WKWebView 那些坑

相关文章

发表评论
暂无评论
官方客服团队

为您解决烦忧 - 24小时在线 专业服务