IOS: WKWebView interactúa con JS

prefacio

Con el rápido desarrollo de Internet móvil, los límites entre el desarrollo web y el desarrollo de aplicaciones nativas se están desdibujando gradualmente. Por un lado, la tecnología web mejora constantemente y muchas funciones que antes solo podían realizarse en aplicaciones nativas, como el almacenamiento fuera de línea, el acceso a la API del dispositivo, etc., ahora pueden realizarse a través de la tecnología web. Por otro lado, el desarrollo de aplicaciones nativas también ha comenzado a adoptar la tecnología web para mejorar la eficiencia del desarrollo y lograr capacidades multiplataforma. Esta tendencia de combinar el desarrollo web con el desarrollo nativo ha traído nuevas posibilidades para el desarrollo de aplicaciones móviles.

Alternancia entre UIWebView y WKWebView

Originalmente, la forma de cargar páginas web en la plataforma iOS era mediante el uso de UIWebView. Sin embargo, con el desarrollo de la tecnología de la plataforma iOS, surgieron gradualmente las limitaciones de UIWebView. En primer lugar, el problema de rendimiento de UIWebView es prominente: necesita consumir mucha memoria y recursos de CPU al cargar páginas web, lo que resulta en una baja eficiencia de la aplicación. En segundo lugar, UIWebView no admite la carga simultánea de varias páginas web, lo que parece impotente en escenarios multitarea. Finalmente, el diseño de la API de UIWebView es relativamente antiguo y no es compatible con los nuevos estándares de tecnología web.

Para resolver estos problemas, Apple introdujo un nuevo componente en iOS 8: WKWebView, que se usa para reemplazar UIWebView. WKWebView utiliza el motor Nitro JavaScript en su diseño, que es un motor eficiente que puede mejorar en gran medida la eficiencia de ejecución de JavaScript. Al mismo tiempo, WKWebView también admite la carga simultánea de varias páginas web y adopta los últimos estándares de tecnología web, lo que permite a los desarrolladores utilizar las últimas tecnologías web.

El principio de interacción entre WKWebView y JavaScript

La interacción entre WKWebView y JavaScript se puede dividir básicamente en dos direcciones: una es que JavaScript llama al código Swift y la otra es que el código Swift llama al código JavaScript.

Para JavaScript que llama al código Swift, WKWebView proporciona WKScriptMessageHandlerun protocolo y los desarrolladores pueden recibir mensajes enviados por userContentController(_:didReceive:)código JavaScript a través de métodos implementando el método del protocolo.postMessage

Para el código Swift que llama al código JavaScript, WKWebView proporciona evaluateJavaScript(_:completionHandler:)un método a través del cual los desarrolladores pueden ejecutar el código JavaScript y obtener el resultado de la ejecución a través del controlador de finalización.

A continuación, use un ejemplo para usar WKWebView para interactuar con JavaScript

1. Crear y configurar WKWebView

Primero, necesitamos crear un proyecto Swift e ViewControllerimportar el módulo WebKit en la compilación predeterminada para admitir el uso de WKWebView.

import WebKit

Deje que ViewController implemente los protocolos WKNavigationDelegate y WKScriptMessageHandler. El protocolo WKNavigationDelegate se usa para manejar eventos de navegación de páginas web y el protocolo WKScriptMessageHandler se usa para recibir mensajes enviados por JavaScript. Además, declare una variable webView de tipo WKWebView.

class ViewController: UIViewController, WKNavigationDelegate, WKScriptMessageHandler { 
     var webView: WKWebView!;
     ...
}

En loadViewel método, primero creamos una WKUserContentControllerinstancia y add(self, name: "nativeCallback")agregamos un controlador de mensajes llamado "nativeCallback" a través del método. Luego, creamos una WKWebViewConfigurationinstancia y userContentControllerestablecemos sus propiedades en el controlador de contenido que acabamos de crear. Finalmente, usamos este objeto de configuración para crear una instancia de WKWebView y asignarla a la propiedad de vista del controlador de vista.

override func loadView() {
    let contentController = WKUserContentController();
    contentController.add(self, name: "nativeCallback")
    
    let config = WKWebViewConfiguration();
    config.userContentController = contentController;
    webView = WKWebView(frame: .zero, configuration: config);
    webView.navigationDelegate = self;
    view = webView;
}

loadViewTenga en cuenta que, dado que no se utiliza ningún archivo Storyboard o Xib para definir el diseño de la vista en Interface Builder, es necesario reescribir el método En este método, es necesario crear y asignar a la vista una instancia de UIView (o su subclase). Atributos del controlador view.

viewDidLoad方法中,我们创建了一个URL请求,并通过webView.load(myRequest)方法加载这个请求,用于加载本地服务器上的index.html文件

override func viewDidLoad() {
    super.viewDidLoad()
    let myURL = URL(string: "http://127.0.0.1:8080")
    let myRequest = URLRequest(url: myURL!)
    webView.load(myRequest)
}

2. 处理JavaScript调用

userContentController(_:didReceive:)方法中,我们处理了JavaScript代码发送的消息。当JavaScript代码通过window.webkit.messageHandlers.nativeCallback.postMessage(message)调用"nativeCallback"的message handler时,这个方法就会被调用。我们在这个方法中检查消息的内容,并显示一个alert对话框。

func userContentController(_ userContentController: WKUserContentController, didReceive message: WKScriptMessage) {
    if message.name == "nativeCallback" {
        if let msg = message.body as? String {
            showAlert(message: msg)
        }
    }
}

func showAlert(message: String) {
    let alertController = UIAlertController(title: "提示", message: message, preferredStyle: .alert)
    let okAction = UIAlertAction(title: "确定", style: .default, handler: nil)
    alertController.addAction(okAction)
    present(alertController, animated: true, completion: nil)
}

3. 调用JavaScript方法

在WKNavigationDelegate的webView(_:didFinish:)方法中,我们调用了JavaScript的displayDate()方法来显示当前的日期。

swiftCopy code
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    webView.evaluateJavaScript("displayDate()") { (any, error) in
        if (error != nil) {
            print(error ?? "err")
        }
    }
}

上述代码中在WKWebView加载完index.html页面后,swift会调用index.html的js方法displayDate()方法来显示当前的日期。

4. Web页面

在index.html页面中,我们定义了两个JavaScript函数:displayDate()nativeCallback()displayDate()函数会将当前的日期显示在id为"date"的p元素中。nativeCallback()函数会通过webkit.messageHandlers.nativeCallback.postMessage('js调用ios')发送一个消息到原生应用。

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8"/>
    <meta name="viewport" content="width=device-width,initial-scale=1,minimum-scale=1,maximum-scale=1,user-scalable=no"/>
    <title>wkwebview</title>
    <style type="text/css">
    	h1 {
	    	color: red;
	    	font-size: 1em;
		}
		body {
		    font-size: 2em;
		}
		button {
		    font-size: 0.5em;
		}
		p {
			font-size: 0.5em
		}
		#tip {
			color: blue;
		}
    </style>
</head>
<body>
    <h1>WKWebview和JS交互</h1>
    
    <div>
    	<p id="tip">ios调用js显示日期:</p>	
    	<p id="date">这是一个段落</p>	
    </div>
    <button type="button" onclick="nativeCallback()">js调用ios</button>
    <script type="text/javascript">
        function displayDate(){
            document.getElementById("date").innerHTML=Date();
        }

        function nativeCallback() {    
            try {
              //使用此方法,会报错,因此使用try-catch
              webkit.messageHandlers.nativeCallback.postMessage('js调用ios');
            } catch(error) {
              console.log('WKWebView post message error: ', error);
            }
        }
    </script>
</body>
</html>

通过上面4个步骤后,可以得到结果,当WKWebView加载页面成功后,对调用index.htmldisplayDate()·方法来显示时间,点击页面上的按钮会弹出提示弹窗

bsbqc-hjhul.gif

以上就是在IOS中使用WKWebViewJavaScript进行交互的基本步骤。这种交互方式为原生提供更大的灵活性,我们可以利用Web技术的便利性,同时保持原生应用的高性能和流畅性。

需要注意的是,虽然WKWebView提供了一套完整的API来和JavaScript进行交互,但我们仍然需要谨慎处理JavaScript发送的消息,防止潜在的安全问题。在实际开发中,我们应该尽量限制JavaScript能够调用的原生方法,并对传递的数据进行严格的验证和过滤。

同时,我们也需要注意WKWebView的性能问题。虽然WKWebView的性能大大优于UIWebView,但它仍然不如原生视图。因此,应该根据应用的具体要求和性能要求,合理选择使用WKWebView和原生视图。

Supongo que te gusta

Origin juejin.im/post/7232299098242105403
Recomendado
Clasificación