H5与iOS原生交互总结

实现WKScriptMessageHandler,约定交互Handler

Apple要求新发布的app不能使用UIWebView。交互只总结WKWebView。
首先要约定 ScriptMessageHandler的name,例如:lvJSCallNativeHandler,具体细节不用说了,
主要回调逻辑实现在

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
复制代码

用Safari浏览器的Develop功能可以调试app内置的H5页面。在console里输入
window.webkit.messageHandlers.lvJSCallNativeHandler,可以打出原生添加的Handler对象。

约定UserAgent

设置customUserAgent来让H5可以区分运行环境,是否在App内,版本是多少,设备型号等。
在需要适配的时候有得用就行了。

标题和加载进度监测

  • 由于WKWebview的estimatedProgress属性是支持KVO的,方便progressView显示加载进度。为了体验更好一点一般会有一个默认值,比如0.15,给用户一个加载快的假象。
  • title属性也是支持KVO的,可以同步修改原生导航条的标题

约定App生命周期里的各个时机的通知方法

例如UIViewController的viewWillAppear:

- (void)viewWillAppear:(BOOL)animated {
    [super viewWillAppear:animated];
    [self.webView evaluateJavaScript:@"window.viewWillAppear && viewWillAppear();" completionHandler:nil];
}

复制代码
原生事件 调js方法,通知H5
viewWillAppear viewWillAppear()
viewWillDisappear viewWillDisappear()
UIApplicationWillEnterForegroundNotification willEnterForeground()
原生返回按钮 lvNativeBackCheck()
原生登录成功 loginOnsuccess()
原生登录失败 loginOnfail()

登录状态打通

原生的登录状态应该在H5里能获得才行。
比如约定H5通过Cookie里的lvsessionid来判断登录状态,那就把lvsessionid写入Cookie,
注意域名的写法

NSHTTPCookie *cookie = [NSHTTPCookie cookieWithProperties:
                            @{NSHTTPCookieDomain: @".example.com",
                              NSHTTPCookiePath: @"/",
                              NSHTTPCookieName: @"lvsessionid",
                              NSHTTPCookieValue: lvsessionid}];
WKHTTPCookieStore *cookieStore = self.webView.configuration.websiteDataStore.httpCookieStore;
[cookieStore setCookie:cookie completionHandler:nil];
复制代码

常用约定方法,参数都是字典,返回值也都是字典

  • 显示Loading lvJSShowLoading; 隐藏Loading lvJSHideLoading
  • 获取位置 lvJSGetLocation
  • 打开相机扫描二维码 lvJSOpenQRCodeScan
  • 打开通讯录 lvJSOpenContacts 没有权限返回错误
  • 读取NSUserDefault存储信息 lvJSGetUserDefaultWithKey; 设置本地存储信息 lvJSSetUserDefaultWithKey
  • 页面跳转 lvJSGoClass, 根据参数className类反射来判断跳哪个页面
  • 浏览历史 lvJSSaveHistory
  • 获取屏幕尺寸和状态栏高度 lvJSGetScreenSize
  • 跳转到iOS系统APP设置页 lvJSGoAppSettingPage
  • 隐藏导航条 lvJSHideNativeNavigationBar;显示导航条 lvJSShowNativeNavigationBar
  • 设置webView是否可以回弹 lvJSSetWebViewBounces
  • 复制文本到剪切板 lvJSCopyToPasteboard

其他特殊约定

  • App拦截特定规则的URL到原生页面的例外约定。

比如:门票详情的URL,piao后是产品id。

https://m.example.com/ticket/piao-983253
复制代码

但是一些id是不能拦截的。这就需要约定例外规则,参数requireh5=1

https://m.example.com/ticket/piao-983253?requireh5=1
复制代码

App在拦截时判断包含requireh5=1,就不会拦截。直接用WebView打开

  • WebView是否多开(点击链接时在新的Controller里打开,而不是在当前controller里刷新)

WebView多开让HybirdApp变得更像原生的。约定参数newtab=1
注意原生实现多开时要用copy和传递request(不要传递url,会丢失部分请求信息)同时也可以约定多开的展示方式,push还是present等

Guess you like

Origin juejin.im/post/7049994741684895758