斯威夫特:WKWebView添加像Android的javascript界面

时间:2019-07-25 14:09:14

标签: android swift webview

我有一个要在网页视图中显示的页面,其中包含动态内容。

在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时不打印?为什么?我误会了操作吗? 这是我的一些js代码,可与androidInterface很好地配合

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上一样将值注入“ android” js。

2 个答案:

答案 0 :(得分:0)

我通过注入手动创建的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)

答案 1 :(得分:0)

很遗憾,无法从 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 界面。