Home > Software design >  Swift project with Javascript two way communication
Swift project with Javascript two way communication

Time:12-22

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?

CodePudding user response:

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) {

    }
}
  • Related