Empresas
Empleos
  • Sobre nosotros
  • Soluciones
    • Publicación de vacantes
      Publica tu vacante y recibe candidatos calificados en 48h.
    • Evaluación de candidatos
      500+ pruebas técnicas y psicológicas, más anti-fraude.
    • Headhunting
      Búsqueda ejecutiva a la medida de principio a fin.
    • Nómina + EOR
      Dispersión de nómina y EOR en más de 15 países de LATAM.
  • Precios
  • Empleos

0

703
Vistas
WKWebView: evalúa JavaScript sin ver cambios

En mi aplicación SwiftUI, usé WKWebView para actualizar algunas etiquetas html desde el lado nativo, usando SwiftUI TextFields. Para que la comunicación funcione, estoy usando el método de evaluación de JavaScript evaluateJavaScript() para enviar datos de nativo a webview.

Mi código se ve así:

 struct DemoView: View { @State private var headline: String = "Initial" var body: some View { NavigationView { VStack { Form { TextField("Your headline", text: $headline) } WebView(headline: $headline) } } } } import WebKit let bridgeHTML = """ <!DOCTYPE html> <html> <head> <meta name="viewport" content="width=device-width, height=device-height, initial-scale=1, minimum-scale=1, viewport-fit=cover"> </head> <body> <h3 id="headline">Headline</h3> <script> // to receive messages from native webkit.messageHandlers.bridge.onMessage = (msg) => { document.getElementById("headline").textContent = msg } </script> </body> </html> """ struct WebView: UIViewRepresentable { @Binding var headline: String class Coordinator: NSObject, WKNavigationDelegate, WKScriptMessageHandler { func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) { } private var owner: WebView init(owner: WebView) { self.owner = owner } var webView: WKWebView? func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) { self.webView = webView self.messageToWebview(msg: self.owner.headline) // initial value loading !! } func messageToWebview(msg: String) { self.webView?.evaluateJavaScript("webkit.messageHandlers.bridge.onMessage('\(msg)')") } } func makeCoordinator() -> Coordinator { return Coordinator(owner: self) } func makeUIView(context: Context) -> WKWebView { let userContentController = WKUserContentController() userContentController.add(context.coordinator, name: "bridge") let configuration = WKWebViewConfiguration() configuration.userContentController = userContentController let _wkwebview = WKWebView(frame: .zero, configuration: configuration) _wkwebview.navigationDelegate = context.coordinator guard let path: String = Bundle.main.path(forResource: "index", ofType: "html") else { return _wkwebview } let localHTMLUrl = URL(fileURLWithPath: path, isDirectory: false) _wkwebview.loadFileURL(localHTMLUrl, allowingReadAccessTo: localHTMLUrl) // _wkwebview.loadHTMLString(bridgeHTML, baseURL: nil) // << used for testing return _wkwebview } func updateUIView(_ webView: WKWebView, context: Context) { // this works for update, but for initial it is too early !! webView.evaluateJavaScript("webkit.messageHandlers.bridge.onMessage('\(headline)')") } }

Funciona, dentro del método de delegado didFinish() configuro los valores iniciales para representar en la página web. Y cuando escribo algo, se actualiza automáticamente en la página web. hasta ahora todo bien, pero si no hago nada durante más tiempo (alrededor de 1 minuto) o si cambio la aplicación (no la cierro) y vuelvo a la aplicación y luego cambio algo en el campo de texto, la página web es ya no se actualiza automáticamente.

Por supuesto, podría ejecutar webView.reload() , pero luego pierdo mi estado anterior. En lugar de Initial , obtengo Titular. Lógico porque esto se configuró dentro de la etiqueta h3, pero eso es lo que quiero evitar.

Entonces, ¿cómo puedo asegurarme de que siempre que se evaluteJavascript() , la página web también se actualice sin perder el estado anterior, sin importar cuánto tiempo espere o si cambio de aplicación? ¿Hay alguna forma de resolver esto?

ingrese la descripción de la imagen aquí

over 4 years ago · Santiago Trujillo
1 Respuestas
Responde la pregunta

0

Esto parece un defecto de Apple, porque se llama a updateUIView, pero evaluateJavaScript (JavaScript interno) genera una excepción, porque se pierde bridge.onMessage y no una función más.

Aquí se encuentra una solución alternativa: restablecer WebView en la activación de la escena (la aplicación pasa a primer plano), ya que se recreó con los estados actuales, se conservan los valores anteriores. Probado con Xcode 13.2 / iOS 15.2

 struct DemoView: View { @Environment(\.scenePhase) var scenePhase @State private var headline: String = "Initial" @State private var reset = false var body: some View { NavigationView { VStack { Form { TextField("Your headline", text: $headline) } WebView(headline: $headline).id(reset) // << here !! .onChange(of: scenePhase) { if case .active = $0 { self.reset.toggle() // << here !! } } } } } }
over 4 years ago · Santiago Trujillo Denunciar
Responde la pregunta
Encuentra empleos remotos

¡Descubre la nueva forma de encontrar empleo!

Top de empleos
Top categorías de empleo
Empresas
Publicar vacante Precios Comercial
Legal
Términos y condiciones Política de privacidad
© 2026 PeakU Inc. All Rights Reserved.
Andres GPT
Recomiéndame algunas ofertas
Necesito ayuda