Swift en sistemas antiguos: mitos y realidad
\n\nImagina la situación: escribiste una aplicación genial en Swift, funciona perfectamente en tu iPhone con iOS 16. Pero llega un usuario con un "dinosaurio" con iOS 7 y se queja de que la aplicación se cierra. O desarrollas una utilidad para Mac y el cliente usa OS X 10.9 Mavericks. ¿Te suena ese dolor? Aclaremos de una vez por todas si las aplicaciones Swift funcionan en versiones antiguas de los sistemas operativos de Apple.
\n\nEsta pregunta es un verdadero éxito en Stack Overflow (más de 10 000 visitas). Y la respuesta no es tan sencilla como nos gustaría. En este artículo no solo daremos teoría seca, sino que mostraremos ejemplos de código reales, explicaremos cómo funciona el runtime de Swift y daremos una lista de verificación para comprobar la compatibilidad.
\n\nRespuesta breve: sí, pero con matices
\n\nSi quieres una respuesta inmediata: las aplicaciones Swift pueden funcionar en OS X 10.9 e iOS 7, pero solo si usas Swift 5.5 o superior. Las versiones más antiguas de Swift (1.x–4.x) no son compatibles físicamente con estos sistemas debido a las particularidades del runtime. ¿Suena extraño? Vamos a analizarlo en orden.
\n\n¿Cómo funciona Swift en sistemas antiguos?
\n\nEl secreto está en la estabilidad ABI (Application Binary Interface). Antes de Swift 5.0, cada aplicación llevaba consigo una copia de la biblioteca estándar de Swift. Esto provocaba que:
\n- \n
- El tamaño de la aplicación aumentara entre 5 y 10 MB \n
- El runtime estuviera estrictamente vinculado a la versión de Swift con la que se compilaba la aplicación \n
- Los sistemas antiguos no tuvieran soporte integrado para Swift \n
A partir de Swift 5.0 (Xcode 10.2), el ABI se volvió estable. Esto significa que la biblioteca estándar de Swift ahora está integrada directamente en iOS, macOS, tvOS y watchOS. Pero hay un detalle: solo está integrada en iOS 12.4+ y macOS 10.14.4+. Para sistemas más antiguos (iOS 7, OS X 10.9), el runtime aún debe incluirse con la aplicación, ¡y esto es posible!
\n\n¿Cuándo fue posible?
\n\nA partir de Swift 5.5 (Xcode 13), Apple añadió soporte para deployment targets antiguos. Ahora puedes compilar una aplicación con IPHONEOS_DEPLOYMENT_TARGET = 7.0 o MACOSX_DEPLOYMENT_TARGET = 10.9, y funcionará.
Así es como se ve en el código de configuración del proyecto:
\n\n// Ejemplo de configuración de deployment target en Swift Package Manager\n// Package.swift\nlet package = Package(\n name: "MyLegacyApp",\n platforms: [\n .iOS(.v7), // iOS 7 y superior\n .macOS(.v10_9) // OS X 10.9 y superior\n ],\n dependencies: [],\n targets: [\n .target(\n name: "MyLegacyApp",\n swiftSettings: [\n .unsafeFlags(["-target", "x86_64-apple-macosx10.9"])\n ]\n )\n ]\n)\n\nEjemplo práctico: aplicación para iOS 7 en Swift
\n\nEscribamos un ejemplo simple que funcione en iOS 7. Ten en cuenta: no podemos usar APIs modernas (por ejemplo, UIAlertController apareció solo en iOS 8).
import UIKit\n\n// Clase compatible con iOS 7\nclass LegacyViewController: UIViewController {\n \n override func viewDidLoad() {\n super.viewDidLoad()\n \n // Usamos el antiguo UIAlertView (funciona en iOS 7)\n let alert = UIAlertView()\n alert.title = "¡Hola desde Swift!"\n alert.message = "Esta aplicación funciona en iOS 7"\n alert.addButton(withTitle: "OK")\n alert.show()\n \n // Alternativa: comprobamos la versión de iOS\n if #available(iOS 8.0, *) {\n // Código moderno para iOS 8+\n let modernAlert = UIAlertController(\n title: "Alerta moderna",\n message: "Solo funciona en iOS 8+",\n preferredStyle: .alert\n )\n modernAlert.addAction(UIAlertAction(title: "OK", style: .default))\n present(mode