Cualquier iOS Developer que haya trabajado en aplicaciones del mundo real sabe que presentar los datos de manera clara y comprensible es tan importante como la lógica detrás de ellos. Ya sea que estés mostrando el saldo de una cuenta bancaria, el progreso de descarga de un archivo o la distancia recorrida en un entrenamiento, la forma en que los números se presentan al usuario final puede definir la calidad de la experiencia de usuario (UX).
En el ecosistema moderno de desarrollo de Apple, formatear numeros en SwiftUI se ha convertido en una tarea sorprendentemente elegante. Atrás quedaron los días en los que dependíamos exclusivamente de complejas configuraciones con NumberFormatter. Gracias a las recientes actualizaciones en la programación Swift, Apple ha introducido una API declarativa, segura y altamente optimizada para manejar formatos directamente en tus vistas.
En este tutorial extenso y detallado, exploraremos a fondo cómo trabajar con números en Swift, utilizando Xcode y SwiftUI para crear experiencias impecables en iOS, macOS y watchOS.
1. La Evolución del Formateo en la Programación Swift
Antes de la llegada de iOS 15 y macOS 12, la forma estándar de convertir un Double o un Int en una cadena de texto legible era utilizando la clase NumberFormatter de Foundation. Aunque poderosa y altamente personalizable, requería mucho código repetitivo (boilerplate). A menudo, tenías que crear instancias estáticas de formateadores para no penalizar el rendimiento de la aplicación.
Con la maduración de SwiftUI, Apple introdujo la API FormatStyle. Esta API es un cambio de paradigma: es declarativa, se integra directamente con los tipos de datos nativos de Swift y está fuertemente tipada. Esto significa que el compilador de Xcode te ayudará a evitar errores en tiempo de ejecución al formatear tus datos.
—
2. El Poder de la API FormatStyle y el método .formatted()
La forma más directa de aplicar formato a un número hoy en día es utilizando el método .formatted() que está disponible en la mayoría de los tipos numéricos estándar (Int, Double, Float, etc.).
Ejemplo Básico
let vistasDePantalla = 14500
let vistasFormateadas = vistasDePantalla.formatted()
// Resultado en una región de habla inglesa: "14,500"
// Resultado en España: "14.500"
El verdadero poder de este enfoque es la localización automática. Como iOS Developer, no tienes que preocuparte por saber si el usuario prefiere comas o puntos para separar los miles; el sistema operativo, ya sea en iOS, macOS o watchOS, lo determina automáticamente basándose en la configuración regional (Locale) del dispositivo del usuario.
—
3. Formatear Números en SwiftUI Directamente en las Vistas
SwiftUI lleva la API FormatStyle un paso más allá al integrarla directamente en sus vistas, especialmente en la vista Text. En lugar de formatear el número antes de pasarlo a la vista, puedes inyectar el valor numérico y el estilo de formato directamente en el inicializador de Text.
Formato Numérico Estándar
Para mostrar un número con formato estándar, utilizamos el parámetro format dentro de la vista Text:
import SwiftUI
struct EstadisticasView: View {
let puntuacion: Double = 12345.678
var body: some View {
VStack(spacing: 20) {
Text("Puntuación del Jugador")
.font(.headline)
// Formatear numeros en SwiftUI es tan sencillo como esto:
Text(puntuacion, format: .number)
.font(.largeTitle)
.bold()
}
.padding()
}
}
Al compilar esto en Xcode, el sistema renderizará “12,345.678” o “12.345,678” dependiendo de la región, aplicando la separación de miles y decimales de manera nativa.
—
4. Controlando la Precisión y los Decimales
Uno de los requerimientos más comunes en la programación Swift es limitar la cantidad de decimales que se muestran en pantalla. La API nos permite encadenar modificadores al formato base .number.
Modificador .precision
Puedes usar .precision(.fractionLength(x...y)) para definir el número mínimo y máximo de decimales permitidos.
import SwiftUI
struct DetallesFinancierosView: View {
let tasaDeInteres: Double = 4.123456
var body: some View {
VStack {
// Muestra exactamente 2 decimales: 4.12
Text(tasaDeInteres, format: .number.precision(.fractionLength(2)))
// Muestra entre 1 y 3 decimales dependiendo del valor: 4.123
Text(tasaDeInteres, format: .number.precision(.fractionLength(1...3)))
}
}
}
Agrupación y Signos
Si necesitas ocultar la separación de miles (por ejemplo, al mostrar un número de ID o un año), puedes desactivar el agrupamiento. También puedes forzar la visualización del signo positivo para indicar un crecimiento.
let año = 2026
let crecimiento = 15.5
// Sin separador de miles (ej. 2026 en lugar de 2,026)
Text(año, format: .number.grouping(.never))
// Forzar la visualización del signo (ej. +15.5)
Text(crecimiento, format: .number.sign(strategy: .always()))
—
5. El Mundo del Dinero: Formateo de Monedas
Manejar divisas es una tarea crítica. Un error común es intentar agregar el símbolo de la moneda manualmente (ej. Text("$\(monto)")). Esto rompe la localización y es una mala práctica de accesibilidad. Para formatear numeros en SwiftUI como moneda, utilizamos .currency.
import SwiftUI
struct CarritoDeComprasView: View {
let total: Double = 1499.99
var body: some View {
HStack {
Text("Total a pagar:")
Spacer()
// Formato de moneda usando el código ISO 4217
Text(total, format: .currency(code: "USD"))
.font(.title2)
.foregroundColor(.green)
}
.padding()
}
}
El formato .currency es extremadamente inteligente. Si la configuración regional del dispositivo es España y el código es “EUR”, mostrará 1.499,99 €. Si la región es Estados Unidos y el código es “EUR”, mostrará €1,499.99. Esto garantiza que tus aplicaciones se sientan nativas y profesionales en cualquier mercado.
—
6. Porcentajes de Forma Sencilla
Al igual que con las monedas, no debes multiplicar por 100 y añadir un “%” a mano. SwiftUI maneja los porcentajes de forma elegante. Ten en cuenta que la API asume que el valor base es la fracción (donde 1.0 = 100%).
import SwiftUI
struct ProgresoView: View {
let nivelDeCarga: Double = 0.854 // 85.4%
var body: some View {
// Muestra 85%
Text(nivelDeCarga, format: .percent.rounded())
// Muestra 85.4%
Text(nivelDeCarga, format: .percent.precision(.fractionLength(1)))
}
}
—
7. Trabajando con Unidades de Medida y Datos
Si estás desarrollando para watchOS, es muy probable que trabajes con datos de salud (distancia, calorías, frecuencia cardíaca). Si desarrollas aplicaciones de utilidades para macOS o iOS, puedes necesitar mostrar tamaños de archivos. Swift ofrece herramientas nativas para esto.
Formateando Bytes (Tamaños de Archivo)
La estructura ByteCountFormatStyle te ahorra la tarea de calcular si un archivo está en KB, MB, GB o TB.
import SwiftUI
struct AlmacenamientoView: View {
let tamañoArchivoEnBytes: Int64 = 10_500_000_000 // Aprox 10.5 GB
var body: some View {
// Xcode compilará esto para mostrar "10.5 GB" (o equivalente regional)
Text(tamañoArchivoEnBytes, format: .byteCount(style: .file))
}
}
Unidades de Medida (Measurement)
Para distancias, pesos y temperaturas, utilizamos el tipo Measurement.
import SwiftUI
struct ClimaView: View {
let temperatura = Measurement(value: 38, unit: UnitTemperature.celsius)
let distancia = Measurement(value: 5.2, unit: UnitLength.kilometers)
var body: some View {
VStack {
// El sistema lo convierte automáticamente a Fahrenheit si el usuario está en EE.UU.
Text(temperatura, format: .measurement(width: .abbreviated))
// Puede mostrar "5.2 km" o "3.2 mi" dependiendo de la región
Text(distancia, format: .measurement(width: .wide))
}
}
}
—
8. Entrada de Usuario: TextFields con Formato y SwiftUI
Mostrar números es solo la mitad del trabajo de un iOS Developer. A menudo, necesitamos que los usuarios introduzcan números (por ejemplo, en una aplicación de finanzas). Aquí es donde TextField en SwiftUI brilla junto a la API de formato, parseando la entrada del usuario y convirtiéndola en un tipo de dato numérico automáticamente.
import SwiftUI
struct PagoView: View {
@State private var montoIngresado: Double? = nil
var body: some View {
Form {
Section(header: Text("Introduce el monto a transferir")) {
TextField("Monto", value: $montoIngresado, format: .currency(code: "EUR"))
#if os(iOS)
.keyboardType(.decimalPad)
#endif
}
if let monto = montoIngresado {
Text("Vas a transferir: \(monto, format: .currency(code: "EUR"))")
.foregroundColor(.blue)
}
}
}
}
Consideraciones Multiplataforma (iOS, macOS, watchOS)
En el ejemplo anterior, notarás la directiva de compilación #if os(iOS). Esto es crucial cuando compartes código entre plataformas en Xcode.
- En iOS, queremos invocar el teclado numérico (
.decimalPad) para mejorar la UX. - En macOS, los usuarios tienen un teclado físico, por lo que
.keyboardTypeno es necesario ni tiene el mismo impacto. - En watchOS, la entrada de texto es muy diferente (Scribble, dictado, o teclado numérico del sistema), y normalmente se maneja con vistas especializadas o controles de incremento/decremento (
Stepper) en lugar de escribir libremente.
—
9. Personalización Avanzada y Creación de Formatos Propios
Aunque los formatos predeterminados cubren el 95% de los casos de uso en la programación Swift, habrá momentos en los que necesites algo específico (por ejemplo, formatear un número de teléfono o un número de tarjeta de crédito).
En SwiftUI, puedes crear tu propio FormatStyle adoptando el protocolo correspondiente.
import Foundation
struct NumeroTarjetaFormatStyle: ParseableFormatStyle {
var parseStrategy: NumeroTarjetaParseStrategy = .init()
func format(_ value: String) -> String {
// Lógica simple: insertar un espacio cada 4 caracteres
let cleanNumber = value.replacingOccurrences(of: " ", with: "")
var formatted = ""
for (index, character) in cleanNumber.enumerated() {
if index != 0 && index % 4 == 0 {
formatted.append(" ")
}
formatted.append(character)
}
return formatted
}
}
struct NumeroTarjetaParseStrategy: ParseStrategy {
func parse(_ value: String) throws -> String {
return value.replacingOccurrences(of: " ", with: "")
}
}
extension FormatStyle where Self == NumeroTarjetaFormatStyle {
static var tarjetaDeCredito: NumeroTarjetaFormatStyle { .init() }
}
Uso en SwiftUI:
TextField("Número de Tarjeta", value: $numeroTarjeta, format: .tarjetaDeCredito)
Este enfoque te permite encapsular lógicas complejas de formateo, manteniendo tus vistas de SwiftUI limpias y declarativas.
—
10. Compatibilidad y Manejo de Versiones Antiguas (iOS 14 y anteriores)
Como iOS Developer, la realidad comercial a menudo dicta que debemos soportar versiones anteriores del sistema operativo. La API FormatStyle introducida en Swift requiere iOS 15, macOS 12 o watchOS 8 como mínimo.
Si tu proyecto en Xcode tiene un “Minimum Deployment Target” inferior a estas versiones, deberás utilizar la clase tradicional NumberFormatter.
¿Cómo integrar NumberFormatter en SwiftUI?
La forma más eficiente es crear un formateador estático y pasarlo al inicializador de Text o TextField.
import SwiftUI
struct LegacyFormatView: View {
let balance: Double = 10500.50
// Crear el formateador una sola vez es vital para el rendimiento
static let currencyFormatter: NumberFormatter = {
let formatter = NumberFormatter()
formatter.numberStyle = .currency
formatter.currencyCode = "USD"
return formatter
}()
var body: some View {
// Uso en iOS 14 e inferiores
Text(NSNumber(value: balance), formatter: Self.currencyFormatter)
}
}
Si bien es más verboso que la nueva API, es una técnica de programación Swift completamente válida y necesaria para proyectos “legacy”. Si estás desarrollando un proyecto verde (desde cero) hoy en día, puedes y debes optar exclusivamente por la API FormatStyle.
—
11. Rendimiento y Buenas Prácticas en Xcode
Al formatear numeros en SwiftUI, es fundamental tener en cuenta el ciclo de vida de la vista. SwiftUI redibuja las vistas de manera muy agresiva cuando cambia el estado.
- Evita el procesamiento pesado en el
body: La API.formatted()está altamente optimizada en Swift, pero si estás realizando cálculos numéricos complejos antes de formatear, hazlo en unViewModelo utiliza.tasko.onAppearpara preparar los datos. - Aprovecha la inferencia de tipos: No especifiques el tipo de dato si Xcode puede inferirlo. Mantiene el código limpio.
- Localización primero: Nunca asumas que tus usuarios leen los números igual que tú. Apóyate siempre en
.currency,.numbery.measurementen lugar de concatenar strings manualmente. - Pruebas Unitarias (Unit Testing): Cuando escribas lógica de formato personalizada (como el ejemplo de la tarjeta de crédito), asegúrate de escribir pruebas en Xcode comprobando diferentes “Locales” para asegurar que tu código no se rompa si el dispositivo se configura en alemán o japonés.
—
Conclusión
Dominar la forma en que presentamos los datos numéricos es un sello distintivo de un iOS Developer experimentado. La evolución de la programación Swift ha traído herramientas increíbles a nuestro entorno de Xcode. Formatear numeros en SwiftUI ha pasado de ser una tarea tediosa y propensa a errores a ser un proceso elegante, seguro y completamente declarativo.
Ya sea que estés construyendo una aplicación financiera para macOS, un tracker de fitness para watchOS o una tienda de comercio electrónico para iOS, aprovechar las capacidades nativas de FormatStyle, .currency, .percent y Measurement garantizará que tu aplicación ofrezca una experiencia premium y localizada para cada usuario alrededor del mundo.








