Estoy creando una aplicación iOS Swift y me gustaría tener una comunicación bidireccional con javascript. Desde javascript necesito escuchar mensajes (json) y enviar jsons. Sé que hay muchas publicaciones que resuelven este problema, pero no puedo hacerlo funcionar porque soy nuevo en el desarrollo de iOS.
Por lo que veo en otras respuestas y/u otras páginas de tutoriales como medium, para hacer esto construyen una clase que implementa el protocolo UIViewController. Pero mi vista es una estructura que implementa el protocolo Vista. ¿Cómo puedo llamar a esta clase con el protocolo UIViewController desde mi vista? ¿Es posible?
Para simplificar las cosas, primero agregué un WebView de WebKit a View usando una estructura y las funciones:
func makeUIView(context: Context) -> WKWebView func updateUIView(_ uiView: WKWebView, context: Context)Esto funcionó bien. Ahora debo agregar la compatibilidad con javascript.
Entonces, si sigo los ejemplos de UIViewController que encontré, veo que debo agregar:
let config = WKWebViewConfiguration() config.userContentController.add(self, name: doSomething) // I'm seeing an error hereel error es:
Argument type 'SwiftUIWebView' does not conform to expected type 'WKScriptMessageHandler'Así que aquí trato de agregar 'WKScriptMessageHandler' a la estructura (lo mismo sucede si hago una extensión):
struct SwiftUIWebView: UIViewRepresentable, WKScriptMessageHandler // Another a couple errors are shownLos errores son:
1. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'NSObjectProtocol' 2. Non-class type 'SwiftUIWebView' cannot conform to class protocol 'WKScriptMessageHandler'Entonces pienso, ok, cambiemos de estructura a clase. Ahora se muestran aún más errores. Algunos de estos están en las dos funciones que hice para el WebView original y tienen errores, en el mismo orden que el anterior:
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 positionAsí que no creo que esté en el camino correcto.
Por lo que pude descifrar, creo que estas clases que implementan el protocolo UIViewController son las vistas de proyectos basados en guiones gráficos. Por ejemplo, este enlace es uno de los enlaces que seguí porque tiene un repositorio de GitHub vinculado y no son solo fragmentos de código.
¿Puedo tener esta funcionalidad en un proyecto de Swift? Y si es así, ¿cómo?
Las vistas de SwiftUI deben ser struct , por lo que debe crear una class separada que se ajuste al protocolo WKScriptMessageHandler y almacenar una instancia de esa clase en su 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) { } }