La superficie de widgets de iOS 26: un App Intent, muchos lugares
Durante años, un widget fue una instantánea. El sistema renderizaba tu vista sobre una línea de tiempo, el usuario la miraba y cualquier toque abría la app. Ese modelo desapareció. Desde iOS 17, un widget puede llevar botones e interruptores que ejecutan código sin abrir nada, y el código que ejecutan es un App Intent1. Lo mismo ocurre con los controles del Centro de Control y con los botones dentro de una Live Activity. Una vez que lo ves así, la superficie de widgets de iOS 26 deja de parecer tres APIs separadas y empieza a verse como una sola: un conjunto de lugares donde el sistema renderizará tus App Intents, cada uno con su propio espacio y la misma maquinaria por debajo.
Ese cambio de enfoque es la idea central de este artículo. Aprende el App Intent una sola vez y enciendes la pantalla de inicio, la pantalla de bloqueo, el Centro de Control, el botón de Acción, la Dynamic Island y (otra vez el mismo intent) Siri y Apple Intelligence. Escribe tres funciones inconexas y haces cuatro veces el trabajo para obtener un resultado peor.
TL;DR
- Widgets interactivos (iOS 17+): coloca un
Button(intent:)oToggle(isOn:intent:)en la vista de un widget; el sistema ejecuta elperform()del App Intent dentro de tu extensión de widget, fuera de la app, y luego recarga la línea de tiempo1. - Controles del Centro de Control (iOS 18+): un
ControlWidgetconstruido a partir deControlWidgetButtonoControlWidgetToggle, respaldado por los mismos App Intents, aparece en el Centro de Control, en la pantalla de bloqueo y en el botón de Acción2. - Live Activities (ActivityKit): un
ActivityAttributesmás unActivityConfigurationimpulsan la pantalla de bloqueo y la Dynamic Island; las actualizaciones dirigidas desde el servidor llegan por push, y los botones del interior también son App Intents3. - iOS 26 agrega el renderizado, no el modelo: los widgets adoptan la presentación de Liquid Glass y los modos de renderizado con tinte, pero la arquitectura de los App Intents como superficie no ha cambiado desde iOS 184.
- El hecho que lo unifica todo: el botón de un widget, un control, una frase de Siri y una acción de Apple Intelligence pueden ser el mismo App Intent. Diseña la capacidad una sola vez.
Widgets interactivos: el botón que no abre la app
El mecanismo es pequeño y vale la pena enunciarlo con precisión. Agregas un Button o un Toggle de SwiftUI a la vista de un widget, pero en lugar de un closure de acción le pasas un App Intent1:
struct WaterWidgetView: View {
let logged: Int
var body: some View {
VStack {
Text("\(logged) glasses")
Button(intent: LogWaterIntent()) {
Label("Add", systemImage: "plus")
}
}
}
}
Cuando el usuario toca, el sistema ejecuta LogWaterIntent.perform() dentro de tu extensión de widget. La app no se abre. El intent hace su trabajo (escribir en el almacén compartido, actualizar un conteo) y la línea de tiempo del widget se recarga para mostrar el resultado.
Un Toggle funciona de la misma manera a través de un SetValueIntent, que recibe el nuevo valor de encendido/apagado que el usuario acaba de definir:
struct ToggleReminderIntent: SetValueIntent {
static let title: LocalizedStringResource = "Toggle Reminder"
@Parameter(title: "Enabled")
var value: Bool
func perform() async throws -> some IntentResult {
ReminderStore.shared.enabled = value
return .result()
}
}
El widget vincula Toggle(isOn: store.enabled, intent: ToggleReminderIntent()), el sistema asigna a value el nuevo estado, ejecuta perform() y recarga. La misma forma que el botón, con un parámetro extra1.
Dos restricciones definen lo que puedes hacer aquí, y ambas son fáciles de violar. Primero, perform() se ejecuta en el entorno restringido de la extensión de widget, con un presupuesto de ejecución ajustado; sirve para un cambio de estado rápido, no para una subida de red ni un cálculo pesado. Segundo, el widget refleja un estado, no anima una interfaz arbitraria. Cambias datos y la línea de tiempo se vuelve a renderizar; no ejecutas una transición personalizada. Diseña la interacción como «cambia un valor, muestra el nuevo valor» y funciona. Pretende más y el sistema te combate.
Controles del Centro de Control: el mismo intent, otra habitación
iOS 18 abrió el Centro de Control, la pantalla de bloqueo y el botón de Acción a controles de terceros, y la API es deliberadamente paralela a la de los widgets2. Un control es un ControlWidget, y su cuerpo es un ControlWidgetButton o un ControlWidgetToggle conectado a un App Intent:
struct LogWaterControl: ControlWidget {
var body: some ControlWidgetConfiguration {
StaticControlConfiguration(kind: "com.example.logWater") {
ControlWidgetButton(action: LogWaterIntent()) {
Label("Log Water", systemImage: "drop.fill")
}
}
}
}
Si LogWaterIntent ya impulsa tu widget interactivo, el control es casi gratis: mismo intent, nuevo envoltorio. Eso es la arquitectura dando frutos. El control no es una segunda implementación de la función; es un segundo punto de montaje para la que ya escribiste. Un control de tipo interruptor usa SetValueIntent exactamente igual que el toggle del widget, de modo que una capacidad de «silenciar», «iniciar sesión» o «alternar modo oscuro» construida una sola vez aparece en el Centro de Control, en la pantalla de bloqueo y en el botón de Acción sin lógica nueva2.
Live Activities: la superficie que se actualiza sola
Las Live Activities son el tercer lugar, y el que tiene más piezas móviles. Un tipo ActivityAttributes define el contenido estático y dinámico, un ActivityConfiguration renderiza la presentación en la pantalla de bloqueo y las regiones de la Dynamic Island, y ActivityKit inicia, actualiza y finaliza la actividad3. Los botones dentro de una Live Activity son, de nuevo, App Intents, así que un control de «pausa» o «siguiente» en la Dynamic Island ejecuta el mismo tipo de intent que el botón del widget.
La pieza que convierte a las Live Activities en una disciplina propia es la ruta de actualización. Un temporizador que actualizas localmente es sencillo. Una actividad impulsada por eventos que ocurren en un servidor (una entrega que avanza, el marcador de un partido que cambia) se actualiza por push: te registras para pushTokenUpdates, envías cargas push de ActivityKit desde tu backend, y el sistema actualiza la pantalla de bloqueo y la Dynamic Island sin que tu app se esté ejecutando3. Eso es genuinamente potente y genuinamente fácil de hacer mal, porque ahora la corrección de tu actividad depende de un contrato con el servidor, de la fiabilidad del push y de una política de fecha de caducidad, no solo del código local.
Qué cambió realmente iOS 26
El titular de los widgets de iOS 26 es la presentación, no la arquitectura. Los widgets adoptan el material Liquid Glass y ganan modos de renderizado con tinte, de modo que coinciden con el nuevo lenguaje de diseño del sistema y se tiñen correctamente en los contextos donde el sistema operativo recolorea el contenido4. Eso importa para cómo se ve un widget en la pantalla de inicio, la pantalla de bloqueo y StandBy, y merece una revisión de diseño. No cambia cómo funciona la interactividad. Si construiste widgets y controles interactivos en iOS 18, el movimiento de iOS 26 es una renovación visual, no una reescritura. Trata con sospecha las afirmaciones de que iOS 26 «introdujo» los widgets interactivos; la interactividad llegó en iOS 17, los controles en iOS 18, e iOS 26 hizo que se vieran como el resto del sistema.
La implicación de diseño de Liquid Glass es real, eso sí. Un widget es contenido que el sistema compone sobre el fondo de pantalla y refracta a través del cristal de la interfaz, así que aplican las mismas reglas que rigen Liquid Glass dentro de una app: respeta la separación entre capa funcional y capa de contenido, y no pelees contra el material con fondos personalizados pesados que el cristal no puede leer.
La arquitectura, dicha sin rodeos
Este es el modelo que vale la pena conservar. Un App Intent es una capacidad nombrada, tipada y descrita. iOS te ofrece un conjunto creciente de lugares donde montar esa capacidad:
- Un
Buttono unToggledentro de un widget. - Un
ControlWidgeten el Centro de Control, la pantalla de bloqueo y el botón de Acción. - Un botón dentro de una Live Activity y su Dynamic Island.
- Una frase de Siri y una acción de Shortcuts.
- Una acción que Apple Intelligence puede invocar en nombre del usuario5.
Cada uno de esos es el mismo tipo AppIntent con un método perform(). El trabajo está en diseñar bien esa capacidad: un nombre claro, parámetros tipados, un perform() rápido e idempotente, y un resultado sensato. Haz eso una vez y las superficies son envoltorios. Este es el mismo argumento que he planteado sobre los App Intents como la verdadera API a tu app y sobre las tres superficies que una app de iOS expone ahora: la superficie de widgets no es una función que construyes, es un lugar donde tus capacidades aparecen una vez que existen.
Cuándo no vale la pena
La superficie de widgets recompensa a las apps con un estado genuinamente consultable de un vistazo y con acciones rápidas: un rastreador, un temporizador, un interruptor, un control de reproducción. No recompensa a todo.
- Sin estado consultable de un vistazo, no hay widget. Si tu app no tiene nada que valga la pena mostrar sin abrirla, un widget es decoración que te cuesta mantenimiento y un objetivo de extensión adicional.
- Las acciones pesadas o lentas no van en
perform()aquí. El entorno de ejecución de widgets y controles es restringido. Si la acción necesita tiempo real o cómputo real, el botón debería abrir la app en un estado preparado, no fingir que hace el trabajo dentro de la extensión. - Una Live Activity para algo que no es en vivo. Las Live Activities son para eventos acotados en el tiempo y que cambian activamente. Usar una como insignia de estado permanente es leer mal la superficie y una forma rápida de acabar en la lista negra del sistema por el presupuesto de actividad.
La habilidad no está en aprender tres APIs. Está en diseñar App Intents que valga la pena montar, y luego montarlos donde el usuario ya está: la pantalla de inicio que revisa, el Centro de Control al que desliza, la Dynamic Island que ya le está mostrando algo. Construye la capacidad una vez, con buen gusto, e iOS te entrega las superficies gratis.
Preguntas frecuentes
¿iOS 26 introdujo los widgets interactivos?
No. Los widgets interactivos llegaron en iOS 17 y los controles del Centro de Control en iOS 18; iOS 26 hizo que adoptaran el material Liquid Glass y el renderizado con tinte para que coincidan con el lenguaje de diseño del sistema4. Trata con sospecha las afirmaciones de que iOS 26 «introdujo» los widgets interactivos: el cambio de iOS 26 es una renovación visual, no una reescritura.
¿Cómo hace realmente su trabajo un botón dentro de un widget de iOS?
El botón ejecuta un App Intent. Un Button o un Toggle en un widget invoca un AppIntent nombrado y tipado con un método perform(), de modo que el widget actúa sin abrir la app. El mismo intent impulsa un control del Centro de Control, un botón de Live Activity, una frase de Siri y una acción de Shortcuts5.
¿Qué cambió realmente para los widgets en iOS 26?
La presentación, no la arquitectura. Los widgets adoptan Liquid Glass y ganan modos de renderizado con tinte para teñirse correctamente en la pantalla de inicio, la pantalla de bloqueo y StandBy4. La interactividad funciona exactamente igual que en iOS 18, así que un widget interactivo existente necesita una revisión de diseño, no una reescritura.
¿Cómo se actualizan las Live Activities cuando la app no se está ejecutando?
Por push. Te registras para pushTokenUpdates, envías cargas push de ActivityKit desde tu backend, y el sistema actualiza la pantalla de bloqueo y la Dynamic Island sin que tu app se esté ejecutando3. Eso hace que la corrección de la actividad dependa de un contrato con el servidor, de la fiabilidad del push y de una política de fecha de caducidad, no solo del código local.
¿Dónde puede aparecer un único App Intent?
El mismo tipo AppIntent se monta en un Button/Toggle de widget, en un ControlWidget del Centro de Control / pantalla de bloqueo / botón de Acción, en una Live Activity y su Dynamic Island, en una frase de Siri, en una acción de Shortcuts, y como una acción que Apple Intelligence puede invocar5. Diseña la capacidad una sola vez y las superficies son envoltorios.
¿Cuándo no debería construir un widget o una Live Activity?
Omite un widget cuando la app no tenga un estado consultable de un vistazo que valga la pena mostrar sin abrirla. Mantén las acciones pesadas o lentas fuera de perform() en el entorno restringido del widget; en su lugar, abre la app en un estado preparado. Y no uses una Live Activity como insignia de estado permanente; son para eventos acotados en el tiempo y que cambian activamente, y usar una mal quema tu presupuesto de actividad.
-
Apple Developer, “Adding interactivity to widgets and Live Activities”. Los widgets interactivos (iOS 17+) usan
Button(intent:)yToggle(isOn:intent:)de SwiftUI respaldados por unAppIntent(oSetValueIntentpara los toggles); elperform()del intent se ejecuta en la extensión de widget sin abrir la app, y la línea de tiempo se recarga para reflejar el resultado. ↩↩↩↩ -
Apple Developer, “Creating controls to perform actions across the system” y el protocolo
ControlWidget. Los controles (iOS 18+) se construyen a partir deControlWidgetButtonyControlWidgetToggleconectados a App Intents, y aparecen en el Centro de Control, en la pantalla de bloqueo y en el botón de Acción. ↩↩↩ -
Apple Developer, “ActivityKit” y “Displaying live data with Live Activities”.
ActivityAttributesyActivityConfigurationdefinen y renderizan la pantalla de bloqueo y la Dynamic Island; ActivityKit inicia, actualiza y finaliza las actividades, y las actualizaciones dirigidas desde el servidor usan push conpushTokenUpdates. ↩↩↩↩ -
Renderizado de widgets en iOS 26: los widgets adoptan el material Liquid Glass y el modo de renderizado con tinte, controlado mediante
WidgetRenderingModey el valor de entorno\.widgetRenderingMode. El modelo de interactividad (App Intents en widgets y controles) no ha cambiado desde iOS 17 (widgets) e iOS 18 (controles). Apple, “WWDC 2025: the new software design” y la documentación de WidgetKit. ↩↩↩↩ -
Apple Developer, “App Intents”. El mismo tipo
AppIntentes la unidad que el sistema expone a través de Siri, Shortcuts, Spotlight, las superficies de widgets y controles, y Apple Intelligence. Análisis del autor sobre el modelo multisuperficie: App Intents Are Apple’s New API to Your App, App Intents 2 and the iOS 26 additions, y the three surfaces of an iOS app. ↩↩↩