1

I'm building an iOS Swift application and I would like to have a two way communication with javascript. From javascript I need to listen for messages (json) and send jsons. I know there are many posts sorting this problem out, but I'm unable make it work since I'm new to iOS development.

From what I see in other responses and/or other tutorial pages such as medium, in order to do this they build a class that implements the UIViewController protocol. But my view is a struct that implements the protocol View. How can I call this class with protocol UIViewController from my view? Is it posible?

In order to make things simpler, I first added a WebView from the WebKit to the View using a struct and the functions:

func makeUIView(context: Context) -> WKWebView
func updateUIView(_ uiView: WKWebView, context: Context)

This worked fine. Now I must add the javascript compatiblity.

So if I follow the UIViewController examples I found, I see that I must add:

let config = WKWebViewConfiguration()
config.userContentController.add(self, name: doSomething) // I'm seeing an error here

The error is:

Argument type 'SwiftUIWebView' does not conform to expected type 'WKScriptMessageHandler'

So here I try to add 'WKScriptMessageHandler' to the struct (same happens if I make an extension):

struct SwiftUIWebView: UIViewRepresentable, WKScriptMessageHandler // Another a couple errors are shown

The error are:

1. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'NSObjectProtocol'
2. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'WKScriptMessageHandler'

So I think, ok let's change from struct to class. Now there are even more errors showing. Some of these are in both of the functions I made for the original WebView have errors, in the same order as above:

1. Protocol 'UIViewRepresentable' requirement 'makeUIView(context:)' cannot be satisfied by a non-final class ('SwiftUIWebView') because it uses 'Self' in a non-parameter, non-result type position
2. Protocol 'UIViewRepresentable' requirement 'updateUIView(_:context:)' cannot be satisfied by a non-final class ('SwiftUIWebView') because it uses 'Self' in a non-parameter, non-result type position

So I don't think I'm on the right track.

From what I could figure out, I believe that these classes implementing UIViewController protocol are the views from projects based on storyboards. For example, this link is one of the links I followed because it has a GitHub repo linked and it's not just code snips.

Can I have this functionality on a Swift project? And if so, how?

1 Answer 1

2

SwiftUI views must be structs, so you need to create a separate class that conforms to the WKScriptMessageHandler protocol and store an instance of that class on your WebView.

struct WebView: UIViewRepresentable {
    private let messageHandler: WebKitMessageHandler

    init(messageHandler: WebKitMessageHandler) {
        self.messageHandler = messageHandler
    }

    func makeUIView(context: Context) -> WKWebView {
        let config = WKWebViewConfiguration()
        config.userContentController.add(messageHandler, name: "name")
        // pass appropriate frame here
        let webView = WKWebView(frame: CGRect.zero, configuration: config)
        return webView
    }

    func updateUIView(_ uiView: WKWebView, context: Context) {

    }
}

class WebKitMessageHandler: NSObject, WKScriptMessageHandler {
    func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {

    }
}
Sign up to request clarification or add additional context in comments.

3 Comments

Thanks for your reply, I'm checking it out. Just to be sure, in the View should I call it like: WebView(messageHandler: WebKitMessageHandler()) ?
@PauDC yes, that's how you should create it
Thank you very much, I'll mark it as solution right away. It took me a while to test it completely because once inside WebKitMessageHandler, I couldn't find the WebView in order to call evaluateJavaScript. I found it inside WKScriptMessage.

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.