H5与iOS原生交互总结

2,441 阅读3分钟

实现WKScriptMessageHandler,约定交互Handler

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

- (void)userContentController:(WKUserContentController *)userContentController didReceiveScriptMessage:(WKScriptMessage *)message;
先判断message.name,然后把message.body解析成NSDictionary
再用NSInvocation调用具体不同对接方法

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

H5d对接示例见nativeUtil-2.5.1.min.js

约定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说明
viewWillAppearviewWillAppear()将要显示
viewWillDisappearviewWillDisappear()将要消失
UIApplicationWillEnterForegroundNotificationwillEnterForeground()App将要到前台
原生返回按钮lvNativeBackCheck()点击原生返回按钮时询问H5要不要拦截处理
原生登录成功loginOnsuccess()给H5处理登录成功的机会,比如跳转页面
原生登录失败loginOnfail()给H5处理登录失败的机会,比如刷新页面,提示需要登录

登录状态打通

原生的登录状态应该在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];

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

方法说明方法名说明
显示LoadinglvJSShowLoading
隐藏LoadinglvJSHideLoading
获取位置lvJSGetLocation
打开相机扫描二维码lvJSOpenQRCodeScan
打开通讯录lvJSOpenContacts没有权限返回错误
读取NSUserDefault存储信息lvJSGetUserDefaultWithKey
设置NSUserDefault本地存储信息lvJSSetUserDefaultWithKey
页面跳转lvJSGoClass根据参数className类反射来判断跳哪个页面
浏览历史lvJSSaveHistory
获取屏幕尺寸和状态栏高度lvJSGetScreenSize
跳转到iOS系统APP设置页lvJSGoAppSettingPage
隐藏导航条lvJSHideNativeNavigationBar
显示导航条lvJSShowNativeNavigationBar
设置webView是否可以回弹lvJSSetWebViewBounces
复制文本到剪切板lvJSCopyToPasteboard
是否开启了精确定位lvJSGetAccuracyAuthorization
获取通知开关的状态lvJSGetNotificationType
navigationController里的堆栈Index  lvIndexOfNav当WebView在第一个的时候 不应该显示左上角的返回按钮

其他特殊约定

  • 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等