JavaScript synchronous native communication to WKWebView

前端 未结 4 520
我在风中等你
我在风中等你 2020-11-29 23:21

Is synchronous communication between JavaScript and Swift/Obj-C native code possible using the WKWebView?

These are the approaches I have tried and have failed.

相关标签:
4条回答
  • 2020-11-29 23:44

    I found a hack for doing synchronous communication but haven't tried it yet: https://stackoverflow.com/a/49474323/2870783

    Edit: Basically you can use the the JS prompt() to carry your payload from the js side to the native side. In the native WKWebView will have to intercept the prompt call and decide if it is a normal call or if it is a jsbridge call. Then you can return your result as a callback to the prompt call. Because the prompt call is implemented in such a way that it waits for user input your javascript-native communication will be synchronous. The downside is that you can only communicate trough strings.

    0 讨论(0)
  • 2020-11-29 23:54

    I also investigated this issue, and failed as you. To workaround, you have to pass a JavaScript function as a callback. Native function needs to evaluate the callback function to return result. Actually, this is the JavaScript way, because JavaScript never wait. Blocking JavaScript thread may cause ANR, it's very bad.

    I have created a project named XWebView which can establish a bridge between native and JavaScript. It offers binding styled API for calling native from JavaScript and vice versa. There is a sample app.

    0 讨论(0)
  • 2020-11-29 23:58

    No I don't believe it is possible due to the multi-process architecture of WKWebView. WKWebView runs in the same process as your application but it communicates with WebKit which runs in its own process (Introducing the Modern WebKit API). The JavaScript code will be running in the WebKit process. So essentially you are asking to have synchronous communication between two different processes which goes against their design.

    0 讨论(0)
  • 2020-11-30 00:03

    I was facing a similar issue, i resolved it by storing promise callbacks.

    The js that you load in your web view via WKUserContentController::addUserScript

    var webClient = {
        id: 1,
        handlers: {},
    };
    
    webClient.onMessageReceive = (handle, error, data) => {
        if (error && webClient.handlers[handle].reject) {
            webClient.handlers[handle].reject(data);
        } else if (webClient.handlers[handle].resolve){
            webClient.handlers[handle].resolve(data);
        }
    
        delete webClient.handlers[handle];
    };
    
    webClient.sendMessage = (data) => {
        return new Promise((resolve, reject) => {
           const handle = 'm' + webClient.id++;
           webClient.handlers[handle] = { resolve, reject };
           window.webkit.messageHandlers.<message_handler_name>.postMessage({data: data, id: handle});
       });
    }
    

    Perform Js Request like

    webClient.sendMessage(<request_data>).then((response) => {
    ...
    }).catch((reason) => {
    ...
    });
    

    Receive request in userContentController :didReceiveScriptMessage

    Call evaluateJavaScript with webClient.onMessageReceive(handle, error, response_data).

    0 讨论(0)
提交回复
热议问题