
-
Conoce WebKit para SwiftUI
Descubre cómo puedes usar WebKit para integrar fácilmente contenido web en tus apps de SwiftUI. Aprende a cargar y mostrar contenido web, comunicarte con páginas web y mucho más.
Capítulos
- 0:00 - Introducción
- 1:54 - Cargar y mostrar contenido web
- 9:37 - Comunicarse con la página
- 15:44 - Personalizar la interacción de contenido
Recursos
Videos relacionados
WWDC25
-
Buscar este video…
Hola, soy Richard, ingeniero del equipo WebKit. WebKit es el motor del navegador en el centro de Safari, Mail e incontables apps en iOS, iPadOS, visionOS y macOS. Durante años, WebKit permitió a desarrolladores crear experiencias ricas y dinámicas, al incorporar todo el poder y la flexibilidad de la web directamente a tus apps, aprovechando la fortaleza de las plataformas de Apple. Este año, estoy encantado de presentarles WebKit para SwiftUI. Con nuestra nueva API SwiftUI, integrar contenido web a tus apps ahora es más fácil que nunca. Creemos que te encantará usar WebKit para SwiftUI para combinar las potentes experiencias web compatibles con WebKit con la facilidad de uso de SwiftUI. Con la nueva API, mostrar contenido atractivo es tan fácil como crear una vista web y proporcionarle una URL, y funciona en todas las plataformas compatibles con WebKit. Ahora es muy fácil comenzar usando WebKit y SwiftUI. Repasemos algunas de las nuevas e increíbles formas de usar esta API para crear tu app. Primero, veremos las distintas formas en que puedes cargar y mostrar contenido web, incluida la carga de recursos locales. Después de eso, hablaremos sobre las diferentes formas de responder a cambios en tu contenido web y, además, cómo puedes generar cambios en el contenido. Por último, repasaremos cómo personalizar la forma en que las personas interactúan con tu contenido web usando modificadores de vista existentes y nuevos, como habilitar la búsqueda en la página, configurar la posición de desplazamiento y muchos más.
Hay mucho por cubrir, así que empecemos. Para mostrar todas las cosas interesantes que puede hacer la nueva API, crearé una app para buscar información de diferentes lagos alrededor del mundo. Mostraré el hermoso contenido web en toda la app y te mostraré cómo cargar el contenido de los artículos y, también, cómo observar las navegaciones y comunicarse con JavaScript para realmente darle vida a tu app. Te mostraré cómo personalizar la experiencia de navegación del contenido exactamente como lo deseas.
Por último, agregaremos los toques finales utilizando una combinación de modificadores de vista nuevos y familiares para mejorar el aspecto y la interactividad de la app. Comencemos a construir la app. Ya tengo parte del código SwiftUI configurado para que nos centremos en integrar las nuevas API de WebKit. Permítanme comenzar con lo básico: mostrar contenido web. La nueva API WebView hace que esto sea increíblemente sencillo. Esta es una nueva vista SwiftUI diseñada para mostrar sin esfuerzo cualquier contenido web. Como vimos antes, para usar un WebView, solo necesitas darle una URL y, automáticamente, cargará y mostrará su contenido. Pero, por supuesto, puede que no quieras usar WebView sólo para mostrar una única URL. En este ejemplo, tenemos un botón que alterna entre dos URL y, nuevamente, le damos la URL a WebView. Ahora, cada vez que se cambie el interruptor, la vista web se cargará automáticamente y navegará a la nueva URL. Es así de simple. Está bien, pero tal vez quieras hacer algo un poco más interesante con tu contenido web, como reaccionar a los cambios en sus propiedades. En estos casos, solo crea una página web y luego conéctala a tu WebView. De ahora en adelante, cualquier cambio hecho al contenido web estará disponible a través de la página web, al igual que el título de la página.
WebPage es una nueva clase Observable que representa tu contenido web. Fue diseñado desde cero para funcionar perfectamente con Swift y SwiftUI.
Usas WebPage para cargar, controlar y comunicarte con el contenido web. La página web se puede utilizar completamente de forma independiente. Pero cuando se combina con WebView, puedes crear experiencias enriquecidas para tu contenido web. Comencemos mostrando algunas de las diferentes formas de cargar contenido web usando WebPage. Una de las cosas más comunes que quizás desees hacer es cargar una URL remota en tu página web. Puedes hacerlo simplemente utilizando la API de carga con una solicitud de URL. Pero WebPage no se limita sólo a cargar URL. También puede cargar contenido HTML directamente proporcionando la cadena HTML y una URL base a la API. La base se usa cuando el sistema resuelve URL relativas dentro del HTML. WebPage también admite la carga directa de distintos tipos de datos, como datos de archivo web. Simplemente proporciónele los datos que quiere cargar, su tipo MIME y su codificación de caracteres y una URL base. En mi app, comenzaré creando una clase ArticleViewModel que represente un artículo específico. Y dentro pondré la página web asociada y el artículo del lago. Para que SwiftUI pueda reaccionar fácilmente a cualquier cambio en la página y el artículo, haré que la clase sea Observable. Ahora configuré la base de la clase, agregaré una función para cargar la URL del lago en la página web. Ahora pasemos al aspecto de la vista. Crearé un WebView usando la página web del modelo. Y llamaré a la función loadArticle del modelo cuando aparezca la vista por primera vez. Para darle un toque extra agradable, también usaré ignoreSafeArea para que la página fluya hasta la parte inferior del dispositivo. Ahora, cuando agregas una nueva URL de artículo a la app y la abres, se cargará y mostrará el contenido en la vista de detalles. Este es realmente un gran comienzo. Pero para que la experiencia sea aún mejor, proporcionaré algunos artículos precargados en la app. WebKit maneja la carga de URL y datos remotos tal y como cabría esperar, desde el primer momento. Pero también te da el poder de cargar contenido incluido en tu app o acceder a archivos locales. Puedes hacer esto con el nuevo protocolo URLSchemeHandler. Déjame explicarte cómo usarlo. Cuando implementas tu propio controlador de esquema, cualquier navegación a una URL con ese esquema pasará por el controlador y utilizará los datos que tú proporciones. Pero antes de profundizar en ello, repasemos primero qué es un esquema. El esquema es la parte de la URL antes de los dos puntos, que en este caso es el esquema HTTPS. WebKit manejará esquemas comunes como https, archivo y acerca de. Pero para esquemas personalizados, como por ejemplo, este esquema de lagos, el protocolo URLSchemeHandler permite que el código de la app maneje la carga de recursos para las URL del esquema de lagos. Para implementar tu propio controlador de esquema personalizado, crea un tipo que se ajuste al protocolo URLSchemeHandler e implementa la función de respuesta del protocolo devolviendo una secuencia asincrónica de resultados de URLSchemeTask. La función también te proporciona un parámetro URLRequest para decidir cómo responder. Al crear la secuencia de eventos, primero debes generar un URLSchemeTaskResult que contenga una URLResponse. Después de generar una URLResponse, solo necesitas proporcionar algunos datos. Esto sirve para casi todos los casos, pero a veces deseas transmitir datos de forma asincrónica. Gracias al tipo de retorno AsyncSequence, también puedes hacerlo fácilmente. Aquí, recibo una única respuesta de forma asincrónica. Y también recibo una AsyncSequence de valores de datos, que luego agrego a la secuencia devuelta. Si la tarea del esquema de URL se cancela en algún momento, la tarea dentro de la función también se cancelará automáticamente. En mi app, quiero tener algunos lagos ya poblados y cargados previamente para que la gente pueda comenzar de inmediato. Para implementar esta funcionalidad, colocaré recursos HTML y CSS en mi app y luego usaré el controlador de esquema personalizado que acabo de crear. Ahora solo necesito registrar el manejador de esquema con la página web. Para hacer esto, crearé un URLScheme utilizando el esquema que quiero manejar. Y en este caso volveré a utilizar lagos. Si proporcionas un esquema que WebKit ya maneja, el inicializador devolverá nil. Luego crearé una configuración de página web y agregaré el controlador de esquema a su diccionario urlSchemeHandlers. También me aseguraré de pasar la configuración cuando esté creando la página web. Con esto, ahora puedo crear algunos valores LakeArticle predeterminados y darles una URL con mi esquema personalizado, para que el contenido web se cargue desde los recursos guardados en el paquete en lugar de obtenerse de la web. Ahora ya sabes cómo cargar y navegar por nuevas páginas. Cuando la página termine de cargarse, quiero completar la barra lateral con su tabla de contenidos. Puedo hacerlo observando los eventos de navegación del contenido web, lo cual es muy fácil de hacer. Ahora puedes acceder fácilmente al estado de navegación mediante la nueva propiedad Observable currentNavigationEvent en WebPage. Una vez que tengas ese evento, puedes obtener su ID de navegación y luego tomar alguna acción según el tipo de evento que sea. Ahora, sé que es mucho con lo que lidiar. Repasemos los diferentes tipos de eventos de navegación. Una navegación se compone de múltiples eventos secuenciales. La navegación siempre comienza con startedProvisionalNavigation. Puedes obtener un evento receivedServerRedirect si el servidor redirige la solicitud. Obtendrás un evento comprometido cuando la página haya comenzado a recibir contenido para el marco principal. El evento final llega cuando se completa la navegación, aunque esto no siempre está garantizado. Una navegación también puede fallar en cualquier punto, en cuyo caso, se emiten los eventos failed o failedProvisionalNavigation. Y cuando se inicia una nueva navegación, currentNavigationEvent reflejará esa navegación. Por lo general, querrás poder reaccionar continuamente a cualquier navegación que se produzca, como cuando alguien hace clic en un enlace o cuando llamas a la función de carga.
Puede hacerlo utilizando la nueva API de observaciones, disponible en Swift 6.2. Usaré Observaciones para crear una secuencia asincrónica a partir de currentNavigationEvent y luego usaré un bucle for-await para observar cada cambio en el evento actual. De esta manera, puedo gestionar cualquier error que surja o actualizar las secciones del artículo una vez que haya terminado de cargarse. Esto hace que responder a cambios de navegación en tu contenido web sea más fácil que nunca. Junto con currentNavigationEvent, hay muchas otras propiedades en WebPage que se pueden observar para detectar cambios y todas funcionan perfectamente con SwiftUI. Por ejemplo, quiero que la barra de navegación de la vista de detalle muestre el título del artículo. Bueno, puedo hacer esto configurando navigationTitle en la propiedad de título de la página web. Eso fue realmente fácil. Hay muchas más propiedades útiles más allá del título de la página, como la URL actual, el progreso de carga estimado, el color del tema y muchas más. Estas propiedades son súper útiles. Pero a veces, deseas obtener información específica de la página que no es una de las propiedades estándar. Así que necesitas algo un poco más flexible. Y también lo hicimos muy fácil. Puedes evaluar directamente JavaScript para comunicarte con una página utilizando la nueva API callJavaScript. Todo lo que tienes que hacer es escribir una función JavaScript como de costumbre y, luego, pasarla al usar callJavaScript. El tipo de retorno de callJavaScript es un valor Cualquiera opcional. Así que asegúrate de convertirlo a un tipo Swift apropiado para que sea más fácil de usar. Esto hace que sea muy fácil implementar mi función parseSections usando el HTML de la página y obteniendo todos los identificadores y títulos de cada sección. También convertiré el resultado en una matriz de estructuras de secciones para que sea más fácil de manejar.
Ahora, la app mostrará las secciones del artículo en la barra lateral tan pronto como se cargue. WebPage también te ofrece la opción de personalizar políticas de navegación exactamente como lo desees, utilizando el nuevo protocolo WebPage.NavigationDeciding. En mi app, implementaré políticas de navegación personalizadas para controlar el comportamiento de las navegaciones del contenido web. Si hay un enlace en una página a un sitio externo, definitivamente quiero que se abra en mi navegador predeterminado en lugar de cargarse dentro de mi app. Lograré esto creando un nuevo tipo NavigationDecider que se ajuste a WebPage.NavigationDeciding. Este protocolo te permite especificar diferentes políticas para los distintos pasos de su navegación, como antes de que suceda, cuando recibes una respuesta y cuando se necesita autenticación. Como quiero determinar si se debe permitir o no una navegación en función de su URL, voy a especificar la política para una acción de navegación. Esta función proporciona la NavigationAction utilizada en la navegación, además de las NavigationPreferences, que puedes ajustar según la solicitud. Si el esquema de URL es lakes o el host es lakes.apple.com, permitiré la navegación, ya que eso significa que el enlace es de la app, no externo. Si este no es el caso, no quiero que la página web en la app continúe la navegación. Entonces lo cancelaré y actualizaré urlToOpen en ArticleViewModel. Ahora que tengo un NavigationDecider personalizado, necesito configurar mi página web para usarlo. Volviendo a ArticleViewModel, crearé un nuevo decisor de navegación y una nueva propiedad urlToOpen. Y actualizaré mi página web para tener en cuenta el decisor de navegación para que utilice la política que especifiqué anteriormente. Ahora que la página web está configurada, queda un paso final para que toda esta funcionalidad se una.
En ArticleView, escucharé los cambios en la propiedad urlToOpen en el modelo. Si la propiedad no es nula, sé que la navegación se canceló. Y entonces usaré el valor del entorno SwiftUI openURL para abrir la URL en el navegador predeterminado. Ahora, la navegación funciona exactamente como quiero. Podemos pasar a las diferentes formas en que puedes personalizar cómo las personas interactúan con tu contenido web usando diferentes modificadores de vista. Comencemos configurando el comportamiento de desplazamiento para que la vista web rebote verticalmente. De forma predeterminada, las vistas web rebotan cuando te desplazas más allá de los bordes verticales u horizontales, incluso si el contenido es más pequeño que la vista web. El modificador estándar scrollBounceBehavior te permite personalizar este comportamiento y funciona muy bien con WebView. Para configurar el eje horizontal para que rebote solo si el contenido es más grande que la vista, se puede configurar el valor .basedOnSize para el eje horizontal. Esta es sólo una de las muchas y potentes funciones de personalización de desplazamiento que admite WebView. Pero eso no es todo. Una novedad de este año en visionOS es la función de desplazamiento, que se puede configurar fácilmente mediante un único modificador de vista.
En visionOS, WebView admite la nueva apariencia ScrollInputKind cuando se utiliza el nuevo modificador webViewScrollInputBehavior. De forma predeterminada, la función de mirar para desplazarse está deshabilitada en WebView. Como queremos que esté habilitada en nuestra app, usaré el modificador y estableceré su comportamiento como habilitado para la apariencia. Algunos de estos artículos son bastante largos, por lo que queremos que sea realmente cómodo para las personas encontrar lo que buscan. Para que las personas puedan buscar artículos fácilmente, agreguemos soporte para buscar en la página. El modificador findNavigator existente ya funciona perfectamente con WebView, por lo que soportar Find-In-Page es realmente muy fácil. Para que se muestre el navegador de búsqueda, agregaré un botón a la barra de herramientas de la app. En iOS y iPadOS, el navegador de búsqueda aparece como parte del teclado en pantalla cuando está visible o en la parte inferior de la vista web. Y en macOS y visionOS, se muestra en la parte superior de la vista web. Creo que la app realmente está empezando a tomar forma ahora. Hagámoslo aún más accesible creando una buena experiencia de desplazamiento. Otra forma sencilla de navegar por un artículo es elegir una sección en la barra lateral y hacer que la vista web se desplace hasta ahí. Necesitaré sincronizar la posición de desplazamiento de la vista web con esta sección seleccionada para que sepas dónde estás. Permítame comenzar agregando una funcionalidad para que cuando se toque una sección en la barra lateral, la vista web se desplace a esa sección. Para desplazarme a una sección, necesito determinar dónde está, lo cual puedo hacer con una función de JavaScript que configuré previamente. Para ejecutar el script, utilizaré nuevamente callJavaScript. Esta vez, sin embargo, también voy a proporcionarle un diccionario de argumentos. Las claves del diccionario se representan en JavaScript como variables locales y sus valores se convierten en valores de JavaScript. Esta es una forma realmente poderosa y fácil de usar para crear funciones genéricas y reutilizables de JavaScript. En ArticleView, voy a agregar un estado para poder controlar la posición de desplazamiento y la sección. Puedes asociar una posición de desplazamiento con una WebView con el nuevo modificador webViewScrollPosition. Ahora, todo lo que necesito hacer es establecer la posición de desplazamiento siempre que la sección cambie usando scrollTo en la posición de desplazamiento y dándole la posición calculada para la sección. Ahora que puedo desplazarme a una sección usando la barra lateral, también quiero que la barra lateral se actualice a medida que me desplazo. El nuevo modificador onScrollGeometryChange de WebView te brinda el poder de hacer exactamente eso y mucho más. Siempre que cambie la geometría de desplazamiento de WebView, como, por ejemplo, su desplazamiento de contenido o tamaño, el modificador usará la transformación que le proporciones y llamará a su cierre si el valor transformado cambia. En el cierre, calcularé la sección más cercana al nuevo desplazamiento y actualizaré la sección seleccionada. Y así, la sección seleccionada y la posición de desplazamiento estarán ahora perfectamente sincronizadas. Con esto, la app Lakes está completa. Pienso que todo salió viento en popa. Combiné WebPage y WebView para cargar y mostrar los artículos, y pude rellenar previamente la app con algunos artículos predeterminados. También mejoré la experiencia del usuario mostrando la tabla de contenidos en la barra lateral y sincronizando la posición de desplazamiento. Cubrimos mucho hoy, así que recapitulemos lo que aprendimos. WebKit para SwiftUI es una API simple pero poderosa de usar que permite la integración perfecta de contenido web en tu app. Proporciona la capacidad de cargar y personalizar la apariencia del contenido web. URLSchemeHandling te permite administrar recursos web locales de manera efectiva. Además, un conjunto de potentes modificadores de vista como webViewScrollPosition y findNavigator adaptan la experiencia del usuario de tu WebView. Estas son solo algunas características de WebKit para SwiftUI. Por lo tanto, recomiendo consultar la documentación para desarrolladores para obtener información más completa. Y por supuesto, como es SwiftUI, tu contenido web se verá increíble en todas las plataformas.
Si ya estás usando la API WebKit de UIKit o AppKit en una app SwiftUI, o si estás creando una app desde cero, ahora es un buen momento para intentar migrar a la nueva API. Asegúrate de revisar también otras novedades de Swift y SwiftUI, como la nueva API de observaciones. Y por último, comparte tus comentarios una vez que pruebes esta nueva API con cualquier cambio o característica que creas que falta. Espero que te unas a nosotros para marcar el comienzo de esta fantástica nueva era de WebKit.
-
-
- 0:00 - Introducción
WebKit, el motor de navegador que impulsa Safari y muchas apps de Apple, ahora tiene una API SwiftUI. Esta nueva API simplifica la integración de contenido web en apps SwiftUI en iOS, iPadOS, visionOS y macOS, lo que te permite combinar experiencias web con la facilidad de uso de SwiftUI y personalizar las interacciones de contenido web.
- 1:54 - Cargar y mostrar contenido web
Una app SwiftUI que permite buscar información sobre lagos de todo el mundo demuestra el funcionamiento de esta nueva API. La app utiliza la nueva API WebView, una vista SwiftUI diseñada para mostrar contenido web sin esfuerzo. Con solo una URL, WebView puede cargar y mostrar páginas web automáticamente y puedes actualizarlo fácilmente para mostrar contenido diferente según las interacciones de alguien, como alternar entre URL. WebPage es una clase Observable que representa contenido web y te permite cargar, controlar y comunicarte. Permite cargar URL remotas, contenido HTML directamente y varios tipos de datos, lo que proporciona flexibilidad en la presentación del contenido web dentro de la app. En la app de ejemplo, una clase 'ArticleViewModel' administra los datos de cada artículo, incluida la WebPage asociada. Esto permite que SwiftUI reaccione fácilmente a los cambios en el contenido de la página y del artículo. Luego se configura la interfaz de la app, con un WebView que muestra el contenido cargado desde 'ArticleViewModel'. Para ofrecer una experiencia de usuario fluida, la app incluye artículos precargados. El nuevo protocolo 'URLSchemeHandler' maneja URL personalizadas dentro de la app. Esto permite que la app cargue contenido incluido directamente dentro de ella, como recursos HTML y CSS, en lugar de buscar todo de la web. Al implementar un controlador de esquema personalizado, la app de ejemplo puede administrar y mostrar de manera eficiente información del lago previamente ingresada, lo que brinda un punto de partida inmediato.
- 9:37 - Comunicarse con la página
La nueva propiedad Observable 'currentNavigationEvent' en WebPage simplifica el monitoreo de la navegación en el contenido web. Ahora puedes observar fácilmente eventos de navegación, como inicios de páginas, redirecciones, confirmaciones de contenido, finalizaciones y fallas, al utilizar la API Observations. Esto permite actualizaciones en tiempo real, como completar una barra lateral con la tabla de contenidos una vez que se carga la página. Además de los eventos de navegación, WebPage ofrece propiedades observables como el título, la URL y el progreso de carga, las cuales se integran perfectamente con SwiftUI. Para tareas más complejas, la API 'callJavaScript' permite la comunicación directa con el HTML de la página. También puedes personalizar las políticas de navegación con el protocolo 'WebPage.NavigationDeciding' y determinar cómo se maneja la navegación, como la apertura de enlaces externos en el navegador predeterminado.
- 15:44 - Personalizar la interacción de contenido
WebKit para SwiftUI te permite integrar sin problemas contenido web en apps y personalizar la apariencia. Utiliza varios modificadores de vista para adaptar la experiencia del usuario. Por ejemplo, puedes configurar el modificador 'scrollBounceBehavior' para deshabilitar el rebote horizontal a menos que el contenido exceda el tamaño de la vista. 'look to scroll' es nuevo en visionOS. Puedes habilitarlo usando el modificador 'webViewScrollInputBehavior', el cual permite desplazarse mirando el contenido. Puedes agregar fácilmente compatibilidad con Find-In-Page al utilizar el modificador 'findNavigator' y colocar un botón en la barra de herramientas para mostrar el navegador de búsqueda. Para mejorar la accesibilidad y la navegación, sincroniza la posición de desplazamiento de WebView con una sección seleccionada en una barra lateral. Haz esto al utilizar funciones de JavaScript para determinar la posición de la sección y luego al asociar la posición con WebView con el modificador 'webViewScrollPosition'. El modificador 'onScrollGeometryChange' mantiene la barra lateral actualizada mientras alguien se desplaza. WebKit para SwiftUI proporciona una API simple pero poderosa para crear una excelente experiencia de usuario en todas las plataformas. Migra a esta nueva API y comparte tus comentarios.