PREGUNTAS Y RESPUESTAS
iOS
¿Qué aportan el tipado y los optionals de Swift a la seguridad del código?
Swift comprueba tipos durante la compilación y representa explícitamente la ausencia de un valor con Optional, que se escribe con ?. Se accede a un optional de manera segura con optional binding o encadenamiento; forzarlo con ! puede provocar un error de ejecución si contiene nil. Esto hace que los casos de ausencia formen parte del diseño de la API en vez de quedar implícitos. Tipos y optionals en The Swift Programming Language
¿Cuál es la diferencia entre tipos de valor y tipos de referencia en Swift?
Las estructuras y enumeraciones son tipos de valor: al asignarlos o pasarlos a una función se comportan como valores independientes. Las clases son tipos de referencia: varias variables pueden apuntar a la misma instancia mutable. Elegí struct cuando el modelo representa un valor y conviene evitar estado compartido; elegí class cuando necesitás identidad compartida, herencia o semántica de referencia. Array, Dictionary y String también son tipos de valor. Value and Reference Types in Swift
¿Para qué sirven los protocolos y los genéricos en una arquitectura iOS?
Un protocolo define capacidades que varios tipos pueden implementar, y los genéricos permiten escribir funciones o tipos que trabajan con cualquier tipo que cumpla ciertas restricciones. Juntos facilitan límites comprobables por el compilador, como un repositorio abstracto que puede tener implementaciones real y de prueba. No hace falta crear protocolos para cada tipo: usalos cuando permitan sustituir implementaciones o expresar una abstracción útil. Protocols y Generics
¿Cómo administra memoria ARC y cómo se rompe un ciclo de retención?
Automatic Reference Counting (ARC) libera una instancia de clase cuando ya no quedan referencias fuertes a ella. Un ciclo ocurre cuando dos objetos se retienen mutuamente, por ejemplo, un delegado y su propietario; esas instancias permanecen vivas aunque la pantalla ya no las use. Revisá las relaciones en el grafo de memoria y usá weak o unowned solo cuando la relación de propiedad lo justifique; weak se vuelve nil al liberarse el objeto. Automatic Reference Counting y diagnóstico de memoria en Xcode
¿Cómo se organiza una app SwiftUI y dónde se modela la navegación?
App es el punto de entrada, marcado con @main; su body declara una o más escenas, y cada escena contiene una jerarquía de vistas. WindowGroup suele representar la ventana principal. Para navegación jerárquica, NavigationStack mantiene una ruta de valores Hashable que SwiftUI relaciona con pantallas mediante navigationDestination. Esto permite representar y restaurar la navegación como estado, sin acoplarla a una secuencia de vistas creadas manualmente. App y NavigationStack
¿Qué significa el ciclo de vida basado en escenas y cómo responde la app al pasar a segundo plano?
SwiftUI administra el ciclo de vida de cada escena. ScenePhase indica si está activa, inactiva o en segundo plano; leído desde una vista, describe su escena, mientras que desde App resume las escenas de la app. Se puede reaccionar para pausar trabajo o guardar estado, pero no conviene depender de un último callback antes de que el sistema suspenda o cierre la app: persistí los cambios importantes durante el uso. Scenes y ScenePhase
¿Qué significa que SwiftUI sea declarativo y qué papel cumple la identidad de una vista?
En SwiftUI se describe qué interfaz corresponde al estado actual, y el framework calcula las actualizaciones necesarias; no se ordena manualmente cada cambio del árbol de vistas. La identidad permite que SwiftUI relacione una vista con su estado entre actualizaciones. En listas, usá identificadores estables y únicos; cambiar una identidad puede hacer que el framework trate la vista como nueva y reinicie su estado local. SwiftUI performance
¿Cómo decide SwiftUI qué vistas actualizar cuando cambian los datos?
Conservá una sola fuente de verdad en el ancestro común más cercano. @State guarda estado local y transitorio; propiedades normales entregan datos de solo lectura, y @Binding permite que un hijo modifique el estado de su padre. Con Observation, un modelo @Observable puede compartirse y las vistas se actualizan cuando cambian las propiedades que leen. @State sigue el ciclo de vida de la vista y no es almacenamiento persistente. Managing user interface state y Managing model data in your app
¿Qué responsabilidades conviene separar en la arquitectura de una app?
Separá presentación, reglas del dominio y acceso a datos según las necesidades del producto, de modo que una vista no tenga que decidir detalles de red o almacenamiento. SwiftUI no obliga a usar un patrón único como MVVM; una vista, un modelo observable y servicios pequeños pueden bastar. Inyectar dependencias —por ejemplo, un servicio de datos— permite probar reglas sin depender de la red, y evita introducir capas que no aportan una frontera útil. Managing model data in your app
¿Cómo modelar navegación programática y enlaces profundos en SwiftUI?
Con navegación basada en valores, el estado de NavigationStack puede ser una colección tipada o NavigationPath. Al recibir un enlace profundo, validá la URL y convertí sus componentes en una ruta válida de la app; después reconstruí el destino con navigationDestination. Mantené los elementos de la ruta ligeros —por ejemplo, identificadores— y cargá los modelos en destino en vez de transportar objetos grandes por la navegación. Understanding the navigation stack
¿Cómo diseñar una petición de red robusta con URLSession?
URLSession ejecuta tareas de datos o descarga; verificá tanto los errores de transporte como el código HTTP y valida la estructura al decodificar la respuesta. Representá estados de carga, éxito y error en el modelo de presentación, y no asumas que una conexión o respuesta válida siempre estará disponible. Añadí límites de espera, cancelación y reintentos solo cuando sean apropiados para la operación, evitando repetir automáticamente mutaciones que no sean idempotentes. URLSession
¿Cómo usar async/await sin bloquear la interfaz ni dejar trabajo huérfano?
async y await expresan operaciones que pueden suspender mientras esperan, por ejemplo, una respuesta de red. La concurrencia estructurada (async let y grupos de tareas) mantiene las tareas hijas dentro del ámbito que las creó y propaga cancelación. La cancelación es cooperativa: la operación debe comprobarla o llamar código que la respete. Un Task no convierte por sí solo trabajo sincrónico pesado en trabajo de fondo. Concurrency in Swift y Task cancellation
¿Qué protegen los actores, y cuándo se usa MainActor o Sendable?
Un actor serializa el acceso a su estado aislado para evitar carreras de datos; sus métodos pueden intercalarse en puntos await, por lo que hay que volver a comprobar invariantes después de suspender. @MainActor aísla operaciones que interactúan con la interfaz. Sendable comunica que un valor puede cruzar dominios de concurrencia de forma segura. Activar el modo de lenguaje Swift 6 aplica comprobaciones estrictas de concurrencia, aunque el nivel de diagnóstico y aislamiento también depende de la configuración del proyecto. Swift concurrency, MainActor
¿Cómo elegir entre UserDefaults, archivos, SwiftData y Keychain?
Usá UserDefaults para preferencias pequeñas y no sensibles; archivos para documentos o datos cuyo formato y acceso administrás; SwiftData para modelos relacionados y consultas persistentes; y Keychain para credenciales, claves y otros secretos. No guardes contraseñas en preferencias ni implementes criptografía propia. Considerá sincronización, migraciones, tamaño y uso sin conexión como requisitos separados al elegir el almacenamiento. SwiftData y Keychain Services
¿Cómo conecta SwiftData los modelos, las consultas y el almacenamiento persistente?
@Model describe clases persistentes; ModelContainer configura el esquema y el almacenamiento, mientras que ModelContext inserta, consulta, elimina y guarda instancias. En SwiftUI, adjuntá un contenedor al árbol de vistas para que @Query y el contexto del entorno puedan acceder a él. Para datos duraderos, planificá cambios del esquema y migraciones; para pruebas, una configuración en memoria evita alterar el almacenamiento real. Preserving your app’s model data across launches
¿Cómo integrar UIKit en una app SwiftUI o migrar gradualmente una app existente?
SwiftUI puede alojar una vista UIKit mediante UIViewRepresentable y una vista de controlador mediante UIViewControllerRepresentable; el coordinador conecta delegados y callbacks. En una app UIKit que adopta SwiftUI, UIHostingController permite presentar vistas SwiftUI. Mantené una sola fuente de verdad y definí claramente qué lado es dueño del ciclo de vida, para evitar sincronización bidireccional ambigua. UIViewRepresentable y Migrating to the SwiftUI life cycle
¿Cómo organizar las pruebas unitarias, de integración y de interfaz?
Las pruebas unitarias verifican lógica aislada; las de integración comprueban que varios componentes colaboren; y las pruebas UI verifican flujos críticos a través de la interfaz. Swift Testing ofrece suites, parámetros y funciones asíncronas; XCTest continúa siendo importante para automatización UI con XCUIAutomation y pruebas de rendimiento. Una misma suite puede contener ambos frameworks, pero no mezcles sus APIs dentro de una misma prueba. Testing in Xcode y XCTest
¿Cómo probar código asíncrono y mantener las pruebas deterministas?
Probá resultados observables —datos, errores y cambios de estado— sin depender de demoras arbitrarias. Inyectá un servicio falso para simular respuestas lentas, fallos y cancelación; cubrí límites y ramas de error además del caso exitoso. Swift Testing admite pruebas asíncronas y parametrizadas; XCTest también ofrece expectativas para coordinar trabajo asíncrono. Evitá que una prueba dependa del estado de red o de una cuenta externa. Swift Testing y asynchronous tests in XCTest
¿Qué hace confiables las pruebas UI con XCUIAutomation?
Automatizá tareas importantes de una persona usuaria, localizando controles por accesibilidad y verificando resultados visibles, no detalles internos de la implementación. Usá datos controlados y un estado inicial reproducible; evitá esperas fijas cuando el framework puede esperar una condición. Reservá pruebas UI para flujos de extremo a extremo que justifiquen su mayor costo frente a pruebas unitarias. XCUIAutomation
¿Qué flujo seguir para diagnosticar un fallo en Xcode?
Reproducí el problema, aislá la ruta afectada y añadí un breakpoint para inspeccionar variables y avanzar por el código. Para fallos difíciles, los breakpoints simbólicos o de excepción pueden detener la ejecución cerca del origen; revisá también los logs y el reporte de crash. Si el comportamiento depende del tiempo, registrá valores con acciones de breakpoint en lugar de asumir que avanzar paso a paso reproduce la misma ejecución. Debugging in Xcode y setting breakpoints
¿Cómo distinguir una fuga de memoria de un uso de memoria esperado?
Observá si el uso de memoria aumenta sin bajar al cerrar pantallas o terminar una operación. El Memory Graph muestra instancias y referencias fuertes; Allocations ayuda a seguir asignaciones a lo largo de una interacción. Un ciclo de retención puede mantener objetos vivos, pero una subida temporal durante carga o procesamiento no demuestra una fuga. Confirmá el patrón con una reproducción repetible y probá en un dispositivo real cuando importe el límite de memoria de iOS. Gathering information about memory use
¿Cómo investigar una pantalla SwiftUI lenta o entrecortada?
Medí antes de cambiar la arquitectura. Instruments con la plantilla SwiftUI muestra cálculos largos de body, actualizaciones frecuentes y hitches. Reducí dependencias de estado innecesarias, evitá trabajo costoso durante el cálculo de la vista y mové operaciones no relacionadas con UI fuera de MainActor. Probá en dispositivos compatibles menos potentes, porque el tiempo disponible para completar una actualización depende de la frecuencia de pantalla y del dispositivo. Understanding and improving SwiftUI performance
¿Qué prácticas mejoran el rendimiento de listas, imágenes y trabajo de fondo?
Usá contenedores diferidos como LazyVStack o List cuando el tamaño de la colección lo justifique, y proporciona identificadores estables para evitar reconstrucciones innecesarias. Procesá imágenes al tamaño de presentación y liberá referencias que ya no se necesitan. Mantené trabajo de red y cómputo pesado fuera del camino de renderizado, y verifica el resultado con Instruments en equipos representativos en vez de optimizar solo a partir de intuiciones. SwiftUI performance y app responsiveness
¿Cómo incorporar accesibilidad y localización desde el diseño?
Usá controles semánticos, etiquetas descriptivas y orden de lectura coherente para VoiceOver; no comuniques estado solo mediante color. Verificá tamaños de texto dinámicos, contraste y tamaños táctiles en distintas configuraciones de accesibilidad. Localizá textos y formatos con los recursos de Xcode, y comprobá expansión de texto y direcciones compatibles con idiomas de derecha a izquierda cuando el producto los soporte. Accessibility fundamentals y localization
¿Qué medidas básicas protegen los datos y las conexiones de una app iOS?
Aplicá mínimo privilegio: pedí permisos cuando sean necesarios y explica su propósito. Guardá secretos pequeños en Keychain; conserva App Transport Security (ATS) para exigir conexiones TLS seguras y evita excepciones HTTP salvo que sean imprescindibles. Usá APIs del sistema para criptografía y transporte seguro, minimizá los datos expuestos en logs y revisá cómo se maneja la sesión al cerrar sesión. Keychain Services y preventing insecure network connections
¿Qué representan la firma de código, los entitlements y el provisioning profile?
La firma identifica quién compiló la app y permite verificar que no se modificó; los entitlements declaran capacidades solicitadas, como grupos de Keychain o notificaciones. El provisioning profile vincula la app, el certificado y las capacidades permitidas para una distribución o pruebas concretas. Xcode puede gestionar la firma automáticamente; si se configura manualmente, hay que mantener certificados y perfiles compatibles con el App ID y canal de distribución. Distribution signing and provisioning y entitlements
¿Qué revisar antes de compilar, archivar y publicar una versión?
Fijá el deployment target, compilá y ejecutá pruebas con una configuración Release, y comprobá que la app funciona en dispositivos y versiones representativos. Generá un archive para distribución, valida firma y entitlements, y probá la compilación candidata en un canal beta antes de publicarla. Revisa metadatos, permisos y reportes de fallos; una compilación Debug del simulador no sustituye la prueba del archive firmado. Distributing your app for beta testing and releases
En una entrevista, ¿cómo diseñarías una búsqueda que funcione sin conexión y evite resultados obsoletos?
Separaría la interfaz y sus estados de un servicio de búsqueda, guardaría una copia local y definiría cuándo el servidor puede actualizarla. Cancelaría la consulta anterior cuando la persona cambie el texto, y evitaría que una respuesta lenta sobrescriba una búsqueda más reciente; un identificador de solicitud o una tarea estructurada ayudan a controlar esa carrera. Probaría coincidencias, ausencia de red, errores, datos almacenados y cancelación con un servicio falso, y mediría búsquedas grandes antes de elegir índices o cachés. Concurrencia de Swift y Swift Testing
Disponibilidad: SwiftData se incorporó en iOS 17 y Observation también tiene requisitos mínimos de sistema; verificá la disponibilidad de API con el deployment target. Swift Testing se incorporó en Xcode 16. Las comprobaciones estrictas de concurrencia dependen de la versión y del modo de lenguaje de Swift configurado en el proyecto. SwiftData, Observation y Swift Testing