3

I am currently trying to port an app from Android to ios that applies a lot of logic through webviews.

In the android version, I can have something such as

function sendInfo(fileName, dataContent){
    Android.saveData(fileName, dataContent);
}

And deal with the interface through the java portion

@JavascriptInterface
public void saveData(String fileName, String dataContents) {
  //.. do something with the received information
}

I am trying to do the same thing inside ios although I am currently having issues. Mind you we are using Swift 3 in IOS10. What I currently have is:

I have created the configuration and controllers inside loadView(), so by the time it reaches viewDidLoad() everything gets displayed on the app.

 override func loadView(){
        super.loadView()

        let contentController = WKUserContentController()
        contentController.add(self as WKScriptMessageHandler, name: "callbackHandlerFile")

        // configuration
        let config = WKWebViewConfiguration()
        config.userContentController = contentController
        self.webView = WKWebView(frame: self.view.frame, configuration: config)
        self.view = self.webView

    }

    override func viewDidLoad() {
        super.viewDidLoad()
        let url = NSURL(fileURLWithPath: Bundle.main.path(forResource: "html/_wv", ofType: "html")!)
        let req = URLRequest(url: url as URL)
        self.webView!.load(req)

    }

My issue comes from the fact that I have seen that the way in which information is send from Javascript to swift is like this:

function sendInfo(fileName, dataContent){
    webkit.messageHandlers.callbackHandlerFile.postMessage(fileName);
    webkit.messageHandlers.callbackHandlerFile.postMessage(dataContent);
}

And then we retrieve them as:

 // message handler delegate method
func userContentController(_ userContentController: WKUserContentController, didReceive message:WKScriptMessage){
    if(message.name == "callbackHandlerFile") {
            print(message.body)    
    }
}

The print statement will print out both messages one after another, meaning that it will print the contents of fileName and then the contents of dataContent because all the data got mashed up on the same instance.

How would I go by obtaining the same effect as the android counterpart? I need to have these two parts on the same place since I need to create some file i/o, so having different callbackHandlers is pretty much out of the question.All I need is to have something that resembles the Android version. Any pointers would be greatly appreciated.

EDIT:

I know that I can pass objects to the message handlers, so I would have something like:

webkit.messageHandlers.callbackHandlerFile.postMessage({fileName: file,data: data_txt});

But still cant't find a way to access this data without the compiler giving me errors since message.body works with Strings

4
  • 1
    Did you try creating a JSON Object with both data and the action you want to try? { "action" : "saveData", "data": { "fileName": fileName, "dataContent" : dataContent } Commented May 29, 2017 at 19:02
  • @piyuj yes, but I do not understand how to retrieve it inside of the message.body portion inside of the Swift code. I am guessing I am going to have to convert the object to something like a dictionary to access its values. Commented May 29, 2017 at 19:13
  • yes that's right, you can cast it to a dictionary Commented May 29, 2017 at 19:13
  • let me try that. If it goes well I'll let you know so that you can put that as an answer and I can close this with your solution as the proper way of handling this lil pickle here. Commented May 29, 2017 at 19:15

1 Answer 1

3

You can handle this creating a JSON Object with both data and the action you want to do.

Example:

{ "action" : "saveData", "data": { "fileName": fileName, "dataContent" : dataContent } }

Then handle the response as a Dictionary like this:

// message handler delegate method
func userContentController(_ userContentController: WKUserContentController, didReceive message:WKScriptMessage){
        guard let body = message.body as? [String: Any] else {
            return
        }
}
Sign up to request clarification or add additional context in comments.

1 Comment

This is amazing piyui. I am especulating that form here I can check the contents of the received information, and from there perform a check of the type of action and ways to handle the data. You have saved me from tons of frustration. Cheers!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.