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 struct
s, 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) {
}
}