关于ios:iOS中web与Js的交互

38次阅读

共计 2170 个字符,预计需要花费 6 分钟才能阅读完成。

  • 问题

    感觉到 uni-app 框架有 pit,公司强推该框架的小哥识趣的闭嘴,思考到全盘替换周期跟老本挺大,基于 uni-app 能打包成 H5,采纳 webview+js 的原生形式集成

    根本构造:原生壳 + webview[iOS & Android] + js

  • 计划

    确定根底框架后,次要的问题就是 web 与 js 的交互,限于技术能力,只谈 iOS 方向

    首先,UIWebView 用的不多,曾经 iOS14+ 了,用 UIWebView 不被 diss 的话,大略你们团队也就那样了,其对应的交互框架为 JavaScriptCore。Pass 不讲

    再次,可拦挡跳转的 url 并解析,以约定好的 key/value,调用原生办法,该交互方式满足简略的性能需要,仅限 web 唤起 iOS 调用,看状况

    接着,WKWebview 中,JS 调用 native 办法,通过 WKScriptMessageHandler 协定,外围是:window.webkit.messageHandlers. 办法名.postMessage(参数),native 调用 JS 就简略很多,外围是:[weblview evaluateJavaScript:xxx completionHandler: ^(id object, NSError * _Nullable error) {}];

    如上:如果有异步操作,怎么办?如果实现 block 岂不更好?

    最初:WebViewJavascriptBridge,来吧,你值得领有

  • 分析
    1.js 调用 native 办法

    - html 中 web 中按钮点击,- bridge 调用 callHandler,- 调用_doSend()
    - 赋值 messagingIframe.src = xxx://__wvjb_queue_message__
    - native 的 webview 执行代理办法 decidePolicyForNavigationAction
    - 获取 url, native 执行 WKFlushMessageQueue
    - webview 执行 evaluateJavaScript,调用 js 的_fetchQueue(),把_doSend() 调用时写入 sendMessageQueue 中的值取出来,即获取 js 传递过去的参数
    - native 办法 flushMessageQueue,解决 js 传递过去的参数,封装在 block 中
    - 留神:js 传递过去的参数,有可能还有 function 回调的存在,function 是解决 js 调用 native 之后,native 的执行后果回调给 js,造成一个 js->native->js 的过程。

    2.native 调用 js 办法

    - native 中的 bridge 调用 callHandler 办法
    - BridgeBase 中调用 -(void)sendData:(id)data responseCallback:(WVJBResponseCallback)responseCallback handlerName:(NSString*)handlerName
    - BridgeBase 中调用_queueMessage
    - 这里有个判断,当 startupMessageQueue!=nil 时,音讯放在数组中,当 =nil 时,间接调用_dispatchMessage
    - native 中 startupMessageQueue 在执行 injectJavascriptFile 办法后会被设置为 nil
    - injectJavascriptFile 追溯可知当 decidePolicyForNavigationAction 中判断 url 的 host=__bridge_loaded__时调用,- 而在 js 中设置的 bridge 时设置的 WVJBIframe.src = 'https://__bridge_loaded__',到此应该不必多问,分析_dispatchMessage
    - _dispatchMessage 中执行_evaluateJavascript,执行的 js 中的办法_handleMessageFromObjC(xxx)
    - Bridge_JS 中查问_dispatchMessageFromObjC,接着调用_dispatchMessageFromObjC
    - 此时设置回调 A -block,外面的数据是 js 中的执行后果,js 在开始的时候注册 registerHandler, 是 key/block,此时通过 key 能够找到对应的 B -block,将 message 传递过去的 data 跟设置的 A -block 当做对应的 key/block 的 B -block 的参数,间接执行该 B -block 即可。可能在 js 的 registerHandler 中获取到 native 传递过去的参数,同时也可能通过 A -block 将 js 的执行后果回调给 native
    

    3. 总结

     初始化时给 web 注入不少料,外围是 1. 拦挡 url,2. 回调实现基于初始化注入字典便于 key/value 形式治理 block 3.evaluateJavaScript 执行 js
    

    4. 延长

     如上的做法适宜 UIWebView&WKWebView。实际上如果只针对 WKWebView 的话,可在_doSend 办法中间接调用 window.webkit.messageHandlers.xxx.postMessage(null),而非设置 src 的形式。可参照 WKWebViewJavascriptBridge
    
  • Game Over。

正文完
 0