Return result from called function in iOS to calling function in WkWebView in JavaScript
Asked Answered
V

4

8

We called a function in iOS from javascript i.e

var data = webkit.messageHandlers.callbackHandler.postMessage("Hello from JavaScript");

I want to assign returned value in data variable from called method in iOS.

iOS Code :

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
        if(message.name == "callbackHandler") {
            print("JavaScript is sending a message \(message.body)")
            how to send data back??
        }
    }

can someone please tell me how to do it??

I know I can use evaluateJavascript to call back another method but due to some restriction I have to return result from same method.

Venezuela answered 19/7, 2017 at 14:27 Comment(1)
I think this is essentially a duplicate of my question a few years ago. Unfortunately there haven't been any answers yet.Tonguelashing
A
5

Here is one approach:

Javascript:

function callNativeCode() {
    webkit.messageHandlers.callbackHandler.postMessage("Hello from JavaScript");
}

// this function will be later called by native code
function callNativeCodeReturn(returnedValue) {
    // do your stuff with returned value here
}

Swift:

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if(message.name == "callbackHandler") {
        print("JavaScript is sending a message \(message.body)")
        webView.evaluateJavaScript("callNativeCodeReturn(0)")
    }
}

Of course this is not very elegant and not synchronous...

There is another approach with promises, you can find out more about it here: http://igomobile.de/2017/03/06/wkwebview-return-a-value-from-native-code-to-javascript/

Atmo answered 23/1, 2018 at 16:6 Comment(3)
Is there a way to integrate the promise uuid generator into the Promise class itself? Even better if done in a transparent way without having to use a different class, but rather using the same new Promise(...) constructor.Meath
It's strongly discouraged to modify the prototypes of standard JavaScript objects. But it is possible (w3schools.com/js/js_object_prototypes.asp)Atmo
Since I recently got some upvotes for this answer I wanted to point out that the Answer from @Stephen Bridgett (WKScriptMessageHandlerWithReply) is the better approach for iOS 14 and above.Atmo
Y
4

iOS 14+ adds a "didReceive:replyHandler" parameter, which can contain a 'reply' object or an 'errorMessage'. This 'replyHandler' is effectively a formal implementation of the above 'evaluateJavaScript' async callback:

Apple documentation for WKScriptMessageHandlerWithReply interface and didReceive:replyHandler

For an example using this 'replyHandler', see this StackOverflow post: iOS 14 API WKScriptMessageHandlerWithReply

Yordan answered 5/6, 2021 at 11:56 Comment(0)
P
0

If you need to get data in JS from Swift, asynchronously, you may also use localStorage.

In Swift :

webView.evaluateJavaScript("localStorage.setItem(\"mykey\",\"myval\")")

In JS :

let myval = localStorage.getItem('mykey')
Pane answered 26/6, 2023 at 17:48 Comment(0)
H
-1

You could give the WebViewJavascriptBridge library a try and see if it fits your needs.

https://github.com/marcuswestin/WebViewJavascriptBridge.

Headlight answered 11/1, 2018 at 2:26 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.