Guía definitiva para almacenar datos en iOS

Guía definitiva para almacenar datos en iOS

Cuando desarrollas una app en iOS, es clave elegir la mejor forma de almacenar datos según el caso de uso. Aquí te doy una revisión práctica de las opciones disponibles en Swift y cuándo utilizarlas. 🚀

Swift Programming Language Logo
Swift - El lenguaje de programación de Apple para iOS

UserDefaults

💡
✅ Ideal para propiedades configuraciones y preferencias del usuario (tema oscuro, idioma, etc.) ❌ No es seguro ni eficiente para datos grandes.
// Guardar datos - Standard settings, Pvalue, CountdownType,
// Bool, Data, Double Float, Int, String, URL, StringArray, Dictionary
UserDefaults.standard.set("valor", forKey: "clave")
UserDefaults.standard.set(25, forKey: "edad")
UserDefaults.standard.set(true, forKey: "premium")

// Leer datos
let valor = UserDefaults.standard.string(forKey: "clave")
let edad = UserDefaults.standard.integer(forKey: "edad")
let premium = UserDefaults.standard.bool(forKey: "premium")

FileManager (Archivos en el sistema)

💡
✅ Perfecto para almacenar imágenes, PDFs, JSONs o cualquier archivo en el sistema de archivos. ❌ No es ideal para datos estructurados.
let fileManager = FileManager.default
let url = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first!
let fileURL = url.appendingPathComponent("datos.txt")

// Escribir archivo
let contenido = "Hola mundo"
try? contenido.write(to: fileURL, atomically: true, encoding: .utf8)

// Leer archivo
let contenidoLeido = try? String(contentsOf: fileURL, encoding: .utf8)
print(contenidoLeido ?? "No se pudo leer")

Keychain

ℹ️
✅ Seguridad máxima para contraseñas, tokens y credenciales. ❌ No es adecuado para datos grandes o configuraciones de usuario.
import Security

// Guardar en Keychain
let password = "miPasswordSegura".data(using: .utf8)!
let query: [String: Any] = [
    kSecClass as String: kSecClassGenericPassword,
    kSecAttrAccount as String: "[email protected]",
    kSecValueData as String: password
]
SecItemAdd(query as CFDictionary, nil)

CoreData

⚠️
✅ Base de datos local ideal para almacenar grandes volúmenes de datos estructurados. ❌ Puede ser complejo de configurar y manejar.
import CoreData

// Configurar Core Data Stack (normalmente en AppDelegate o SceneDelegate)
lazy var persistentContainer: NSPersistentContainer = {
    let container = NSPersistentContainer(name: "DataModel")
    container.loadPersistentStores { _, error in
        if let error = error {
            fatalError("Error cargando Core Data: \(error)")
        }
    }
    return container
}()

// Guardar contexto
func saveContext() {
    let context = persistentContainer.viewContext
    if context.hasChanges {
        try? context.save()
    }
}

SwiftData (iOS 17+)

💡
✅ Alternativa moderna y más sencilla que CoreData. ❌ Solo disponible en iOS 17+.
import SwiftData

@Model
class User {
    var id: UUID
    var name: String
    var email: String
    
    init(name: String, email: String) {
        self.id = UUID()
        self.name = name
        self.email = email
    }
}

// En tu App principal
@main struct MyApp: App {
    var body: some Scene {
        WindowGroup {
            ContentView()
                .modelContainer(for: User.self)
        }
    }
}

SQLite (GRDB, SQLite.swift)

ℹ️
✅ Flexibilidad completa SQL personalizable y más control que CoreData. ❌ Más complejo e implementar.
import SQLite3

// Ejemplo básico con SQLite3
var db: OpaquePointer?

// Abrir base de datos
let fileURL = try! FileManager.default
    .url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: false)
    .appendingPathComponent("database.sqlite")

if sqlite3_open(fileURL.path, &db) == SQLITE_OK {
    print("Base de datos abierta exitosamente")
} else {
    print("Error al abrir base de datos")
}

Realm

💡
✅ Alternativa más rápida y sencilla que CoreData. ❌ Librería de terceros.
import RealmSwift

class Dog: Object {
    @Persisted var name: String = ""
    @Persisted var age: Int = 0
    @Persisted var breed: String = ""
}

// Usar Realm
let realm = try! Realm()

// Escribir
let dog = Dog()
dog.name = "Rex"
dog.age = 3
dog.breed = "Golden Retriever"

try! realm.write {
    realm.add(dog)
}

// Leer
let dogs = realm.objects(Dog.self)
print("Hay \(dogs.count) perros en la base de datos")

¿Cuál debes usar?

Analiza según las necesidades real necesidades, recuerda que ninguna opción pueden existir muchas opciones, no todas se adaptan bien a cada proyecto, pero aquí tienes una guía detallada de las opciones más usadas en cada uno.

💡
¿Te gustó esta guía? Puedes encontrar más tutoriales sobre desarrollo iOS en mi perfil. ¡No olvides seguirme para más contenido!