iOS 14 API WKScriptMessageHandlerWithReply 如何从 iOS

iOS 14 引入了一种新方法来接收 javascript 调用并使用 WKScriptMessageHandlerWithReply 而不是 WKScriptMessageHandler(在 WebKit 视图内)提供响应。然而文档基本上不存在。这是如何运作的?



宝慕林4294392
浏览 204回答 1
1回答

侃侃无极

我对此进行了深入研究,发现它使用 Javascript Promises 来提供回调机制(并且从应用程序代码返回到 javascript 的响应必须是异步的)。下面是一些示例代码来说明:快速代码:import UIKitimport WebKitimport PureLayoutfinal class ViewController: UIViewController {&nbsp; &nbsp; var webView : WKWebView?&nbsp; &nbsp; let JavaScriptAPIObjectName = "namespaceWithinTheInjectedJSCode"&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; override func viewDidLoad() {&nbsp; &nbsp; &nbsp; &nbsp; super.viewDidLoad()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; //-------&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; guard let scriptPath = Bundle.main.path(forResource: "script", ofType: "js"),&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let scriptSource = try? String(contentsOfFile: scriptPath) else { return }&nbsp; &nbsp; &nbsp; &nbsp; let userScript = WKUserScript(source: scriptSource, injectionTime: .atDocumentEnd, forMainFrameOnly: true)&nbsp; &nbsp; &nbsp; &nbsp; let config = WKWebViewConfiguration()&nbsp; &nbsp; &nbsp; &nbsp; let userContentController = WKUserContentController()&nbsp; &nbsp; &nbsp; &nbsp; userContentController.addUserScript(userScript)&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; // REQUIRES IOS14&nbsp; &nbsp; &nbsp; &nbsp; if #available(iOS 14, *){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; userContentController.addScriptMessageHandler(self, contentWorld: .page, name: JavaScriptAPIObjectName)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; config.userContentController = userContentController&nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; webView = WKWebView(frame: .zero, configuration: config)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; if let webView = webView{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; view.addSubview(webView)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; webView.autoPinEdgesToSuperviewMargins() // using PureLayout for easy AutoLayout syntax&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if let htmlPath = Bundle.main.url(forResource: "page", withExtension: "html"){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; webView.loadFileURL( htmlPath, allowingReadAccessTo: htmlPath);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }&nbsp; &nbsp; // need to deinit and remove webview stuff&nbsp; &nbsp; deinit {&nbsp; &nbsp; &nbsp; &nbsp; if let webView = webView{&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; let ucc = webView.configuration.userContentController&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ucc.removeAllUserScripts()&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; ucc.removeScriptMessageHandler(forName:JavaScriptAPIObjectName)&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}extension ViewController: WKScriptMessageHandlerWithReply {&nbsp; &nbsp; func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage, replyHandler: @escaping (Any?, String?) -> Void) {&nbsp; &nbsp; &nbsp; &nbsp; if message.name == JavaScriptAPIObjectName, let messageBody = message.body as? String {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; print(messageBody)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; replyHandler( 2.2, nil ) // first var is success return val, second is err string if error&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; }}这是通过 Swift 代码加载并注入到网页中的 script.js:function sampleMethodTheHTMLCanCall( inputInfo, successFunc, errorFunc ) {&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; var promise = window.webkit.messageHandlers.namespaceWithinTheInjectedJSCode.postMessage( inputInfo );&nbsp; &nbsp;&nbsp;&nbsp; &nbsp; promise.then(&nbsp; &nbsp; &nbsp; function(result) {&nbsp; &nbsp; &nbsp; &nbsp; console.log(result); // "Stuff worked!"&nbsp; &nbsp; &nbsp; &nbsp; successFunc( result )&nbsp; &nbsp; &nbsp; },&nbsp; &nbsp; &nbsp; function(err) {&nbsp; &nbsp; &nbsp; &nbsp; console.log(err); // Error: "It broke"&nbsp; &nbsp; &nbsp; &nbsp; errorFunc( err )&nbsp; &nbsp; &nbsp; });}这是可以调用应用程序代码的 page.html 示例 HTML:<html>&nbsp; &nbsp; <meta name="viewport" content="width=device-width" />&nbsp; &nbsp; &nbsp; &nbsp; <script>&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function handleInfoFromApp( fromApp ){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; document.getElementById("valToWrite").innerHTML = fromApp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; function handleError( err ){&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;&nbsp;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; </script>&nbsp; &nbsp; <h1 id="valToWrite">Hello</h1>&nbsp; &nbsp; <button onclick="sampleMethodTheHTMLCanCall( 'inputInfo', handleInfoFromApp, handleError )">Load Info from App</button>&nbsp; &nbsp;&nbsp;</html>上面的 HTML 提供了稍后在 javascript 发起的请求成功或失败时由应用程序扩展代码调用的函数。
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

JavaScript