Selección parcial de texto en SwiftUI con iOS 27
Arturo Rivas Arias
Desde iOS 15, SwiftUI permite hacer seleccionable el contenido de una vista Text con el modificador .textSelection(.enabled). La API era sencilla y útil, pero en iPhone y iPad tenía una limitación importante: al mantener pulsado, las acciones del menú contextual se aplicaban al bloque completo. Si una pantalla mostraba un párrafo largo, el usuario podía copiarlo entero, pero no elegir únicamente una palabra o una frase.
iOS 27 elimina esa limitación y lo hace sin añadir una API nueva. El mismo modificador muestra ahora el resaltado y los indicadores de selección del sistema, de modo que es posible ajustar el rango y actuar solo sobre el fragmento escogido. El cambio parece pequeño, pero acerca el comportamiento de Text al que los usuarios ya esperan encontrar en Safari, Notas y otras aplicaciones del sistema.
La API no ha cambiado
El código necesario sigue siendo exactamente el mismo:
import SwiftUI
struct MaintenanceNoticeView: View {
private let instructions = """
El servicio permanecerá en modo de solo lectura durante la actualización. \
Las operaciones pendientes se reanudarán automáticamente al finalizar.
"""
var body: some View {
Text(instructions)
.font(.body)
.textSelection(.enabled)
.padding()
}
}
En iOS 27, una pulsación prolongada sobre este texto permite seleccionar una palabra, ampliar el rango con los indicadores y copiar únicamente ese fragmento. En iOS 26 y versiones anteriores, el menú contextual continúa trabajando con el contenido completo de la vista Text.
Esto significa que no hace falta envolver el código en if #available(iOS 27, *), ya que textSelection(_:) está disponible desde iOS 15. Tampoco existe una variante nueva que haya que adoptar: es el sistema operativo el que proporciona la interacción mejorada cuando ejecuta la aplicación.
Qué cambia según la versión del sistema
| Comportamiento | iOS 26 y anteriores | iOS 27 |
|---|---|---|
| Pulsación prolongada | Abre el menú contextual | Inicia la selección de texto |
| Alcance inicial | Todo el contenido de Text | Una palabra o rango concreto |
| Ajuste mediante indicadores | No disponible | Disponible |
| Copia de un fragmento | No disponible de forma nativa | Disponible |
| Cambios en el código | Ninguno | Ninguno |
La compatibilidad hacia atrás es especialmente interesante para aplicaciones que todavía mantienen iOS 18, iOS 26 u otra versión anterior como deployment target. Se puede conservar una única implementación y aceptar que la experiencia se adapte a las capacidades del sistema. Los usuarios de iOS 27 obtienen la selección parcial, mientras que los demás conservan el comportamiento previo.
Activar la selección desde un contenedor
Apple permite aplicar textSelection(_:) tanto a una vista concreta como a un contenedor. Esto evita repetir el modificador cuando una pantalla contiene varios bloques de texto que deberían poder copiarse.
import SwiftUI
struct DiagnosticReportView: View {
let requestID: String
let endpoint: String
let responseCode: Int
let message: String
var body: some View {
ScrollView {
VStack(alignment: .leading, spacing: 12) {
Text("Informe de diagnóstico")
.font(.title2.bold())
LabeledContent("Request ID", value: requestID)
LabeledContent("Endpoint", value: endpoint)
LabeledContent("Estado", value: String(responseCode))
Text(message)
.font(.body)
Text("Generado localmente en el dispositivo")
.font(.caption)
.foregroundStyle(.secondary)
}
.frame(maxWidth: .infinity, alignment: .leading)
.padding()
}
.textSelection(.enabled)
}
}
Aplicarlo al ScrollView configura como seleccionable el texto de sus descendientes sin convertir la pantalla en un editor. Cada control conserva su estructura y el usuario sigue interactuando con una interfaz de lectura. Si se necesita que varios fragmentos formen un único bloque continuo de selección, conviene representarlos dentro del mismo Text en lugar de asumir que diferentes vistas se comportarán como un solo documento.
Seleccionar no significa editar
Text continúa siendo una vista de solo lectura. iOS 27 mejora la selección visual y las acciones del sistema, pero no añade un cursor de edición, teclado, reemplazo de contenido ni un Binding con el rango seleccionado. El modificador textSelection(_:) recibe un valor de TextSelectability, como .enabled o .disabled; no expone el fragmento elegido a la lógica de la aplicación.
Tampoco debe confundirse con el tipo TextSelection. Aunque los nombres son parecidos, cumplen funciones diferentes. TextSelection representa selecciones en controles de entrada como TextField y TextEditor, donde la aplicación sí puede necesitar conocer o modificar la posición del cursor y los rangos seleccionados. .textSelection(.enabled), en cambio, habilita la interacción que gestiona el sistema sobre contenido presentado para lectura.
Esta diferencia permite escoger la herramienta apropiada:
Textcon.textSelection(.enabled)para documentación, mensajes, resultados, identificadores, términos legales o cualquier contenido que deba poder copiarse sin editarse.TextEditorcuando el usuario debe escribir, modificar o dar formato al contenido y la selección forma parte del estado del editor.UITextView,NSTextViewo TextKit cuando la aplicación necesita acciones especializadas, rangos programáticos, anotaciones, selección sobre una vista personalizada o un motor de edición propio.
Un modificador que se propaga por el entorno
El valor de selección se transmite por la jerarquía de SwiftUI. Esto permite habilitarlo para una sección completa y desactivarlo de nuevo en una zona concreta si contiene texto puramente decorativo o información que no tiene sentido copiar.
struct PrivacySummaryView: View {
var body: some View {
VStack(alignment: .leading, spacing: 16) {
Text("Resumen de privacidad")
.font(.title.bold())
.textSelection(.disabled)
Text("Los datos de actividad se procesan en el dispositivo y se eliminan al cerrar la sesión.")
Text("Identificador de política: PRIVACY-2026-08")
.font(.footnote.monospaced())
}
.textSelection(.enabled)
.padding()
}
}
Este patrón resulta más mantenible que añadir el modificador a cada vista individual, pero merece la pena usarlo con intención. Habilitar la selección en una pantalla completa puede afectar también a etiquetas o textos secundarios que no aportan nada al portapapeles. Delimitar el ámbito produce una interacción más limpia.
Accesibilidad y coherencia con el sistema
Adoptar la selección nativa no solo evita implementar gestos y menús manualmente. En su sesión de WWDC26 sobre aplicaciones de lectura accesibles, Apple explica que Text seleccionable, TextEditor, UITextView y NSTextView adoptan automáticamente la infraestructura de entrada de texto necesaria para ofrecer navegación granular y selección accesible con tecnologías como VoiceOver y Speak Screen.
Una implementación personalizada basada en una pulsación prolongada y una copia manual puede reproducir la acción más visible, pero también puede perder selección por palabra, navegación por caracteres, comportamiento bidireccional, integración con tecnologías de asistencia y futuros cambios del sistema. Cuando la necesidad es simplemente permitir que el usuario copie contenido, la API de SwiftUI suele ser una solución más completa.
Cuándo merece la pena habilitarlo
La selección parcial aporta valor cuando una pantalla contiene información que el usuario puede necesitar trasladar a otro lugar. Algunos casos especialmente claros son:
- Mensajes de error y códigos de diagnóstico.
- Números de seguimiento, referencias o identificadores de operaciones.
- Documentación técnica y fragmentos de configuración.
- Condiciones contractuales, avisos y políticas de privacidad.
- Respuestas generadas, transcripciones y contenido formativo.
En textos muy breves, como un único número de pedido, puede seguir siendo más cómodo ofrecer un botón de copia explícito. Para contenido extenso o no predecible, la selección parcial evita tener que anticipar qué fragmento querrá conservar cada persona. Ambas interacciones pueden coexistir: el botón resuelve la acción frecuente y la selección nativa cubre los casos menos habituales.
Una mejora automática, pero que conviene probar
Aunque no exista una migración de código, sigue siendo recomendable revisar las pantallas seleccionables en iOS 27. Una pulsación prolongada puede competir con otros gestos personalizados, menús contextuales, enlaces incrustados o elementos superpuestos. También conviene comprobar textos con varias líneas, contenido traducido, tamaños de letra de accesibilidad y escritura de derecha a izquierda.
Las pruebas deberían incluir al menos la selección de una palabra, la ampliación hasta varias líneas, la copia del resultado y la interacción con VoiceOver. Así se verifica no solo que el nuevo comportamiento aparece, sino que encaja con el resto de la interfaz.
Conclusión
iOS 27 convierte .textSelection(.enabled) en una herramienta mucho más útil para interfaces de sólo lectura. El código y la disponibilidad de la API permanecen intactos, pero el usuario deja de estar limitado al bloque completo y puede escoger exactamente el rango que necesita.
La mejora recompensa una práctica muy propia de SwiftUI: declarar la intención y dejar que el sistema adapte la interacción. Las aplicaciones que ya habilitaban la selección reciben un comportamiento más preciso en iOS 27, mantienen la compatibilidad con versiones anteriores y evitan sustituir una capacidad del sistema por implementaciones personalizadas más frágiles.