Swift:WKWebView 添加类似 Android 的 javascript 界面

Posted

技术标签:

【中文标题】Swift:WKWebView 添加类似 Android 的 javascript 界面【英文标题】:Swift: WKWebView add javascript interface like Android 【发布时间】:2019-07-25 14:09:14 【问题描述】:

我有一个页面,我想在 web 视图中显示动态内容。

android上我可以通过界面简单地做到这一点,这是界面:

class WebAppInterface (val context: Context, val userId: Long, val  type: String) 
    @javascriptInterface
    fun getId(): Long 
        return userId
    

    @JavascriptInterface
    fun getBaseUrl(): String
       return Configuration.getInstance().userConfig.getStoredBaseUrl();
    

    @JavascriptInterface
    fun getGetStatType(): String
       return type;
    

webview.addJavascriptInterface(WebAppInterface(this.applicationContext, id, statisticsType!! ), "android")

我如何在 ios 上做同样的事情,在我搜索后我得到了这个:

let contentController = WKUserContentController()
        contentController.add(self, name: "android") // -> Set a listener

        let config = WKWebViewConfiguration()
        config.userContentController = contentController

        let scriptString = "????? What write ir?"
        let script = WKUserScript(source: scriptString, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true)
        config.userContentController.addUserScript(script)

        webView = WKWebView(frame: .zero, configuration: config)

还有委托方法:

 func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) 
    print(message)

在委托方法中,当它到达关键字android时它不打印?为什么?我误解了手术吗? 这是我的一些与 androidInterface 配合良好的 js 代码

function getSteps() 
    const url = android.getBaseUrl() + 'patient/' + android.getId() + '/statistics/steps?from=' + from + '&to=' + to;
    Http.open("GET", url);
    Http.setRequestHeader('Authorization', 'Bearer ' + android.getToken())
    Http.send();

如何将值注入“android”js,就像我在 android 上所做的那样。

【问题讨论】:

可能重复:***.com/questions/51998861/… 【参考方案1】:

我通过注入像这样手动创建的 android 对象解决了这个问题:

let scriptString = """
                       var android = 
                            getGetStatType: function() 
                                return 'sleep';
                            ,
                            getId: function() 
                                return 98;
                            ,
                            getBaseUrl: function() 
                                return 'baseUrl';
                            ,
                            getToken: function() 
                                return 'myToken';
                            
                       ;
                       """
    let script = WKUserScript(source: scriptString, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true)
    config.userContentController.addUserScript(script)

【讨论】:

【参考方案2】:

不幸的是,无法从 javascript 同步调用 swift 方法来获取值。只有一种可能的方式是使用 WKUserContentController 的异步方式。在您的情况下,您很幸运,价值观不是动态的。例如,它不能用于获得一些随时间变化的值,例如GPS 位置。

斯威夫特

webView.configuration.userContentController.add(self, name: "someName")

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) 
    print(message.name, message.body)
    webView.evaluateJavaScript("window.asyncResponseFromIos(123)")

JS

window.webkit.messageHandlers.someName.postMessage("data")

所以在 JS 中不可能有 android 和 ios 的通用同步接口。这就是为什么我要基于 Promise 制作 JS 接口。在 JS 中,我将通过调用例如从 android/ios 获得价值。 var value = await window.mobileAppInterface.get("someKey", "somePayload") 目标是拥有独立于应用平台的通用javascript接口。

【讨论】:

以上是关于Swift:WKWebView 添加类似 Android 的 javascript 界面的主要内容,如果未能解决你的问题,请参考以下文章

在 iOS 10 + Swift 3 中以编程方式在我的 WKWebView 上方添加 UILabel

使用 Swift 4 滚动 WKWebview

WKWebView 因某些查询而崩溃(iOS Swift)

在 iOS 9 中遇到 WKWebview 和 UIWebView 问题

从使用 wkwebview 返回值的 javascript 调用 swift 函数

在 Swift 中删除 WKWebView 附件栏