Overview of iOS Storage Options

Choosing the right data persistence method is crucial for iOS app performance and user experience. This guide covers all major storage options with real-world examples.



1. UserDefaults - Simple Key-Value Storage

// Basic UserDefaults usage
UserDefaults.standard.set("John Doe", forKey: "username")
UserDefaults.standard.set(true, forKey: "isFirstLaunch")
UserDefaults.standard.set(42, forKey: "userAge")

// Reading values
let username = UserDefaults.standard.string(forKey: "username")
let isFirstLaunch = UserDefaults.standard.bool(forKey: "isFirstLaunch")
let userAge = UserDefaults.standard.integer(forKey: "userAge")

// Custom objects with Codable
struct UserPreferences: Codable {
    let theme: String
    let notifications: Bool
    let language: String
}

let preferences = UserPreferences(theme: "dark", notifications: true, language: "en")
if let encoded = try? JSONEncoder().encode(preferences) {
    UserDefaults.standard.set(encoded, forKey: "userPreferences")
}




When to Use UserDefaults

  • App settings and preferences
  • Simple configuration data
  • Small amounts of data (<1MB)
  • Data that needs to persist between app launches

2. CoreData - Object-Relational Mapping

// CoreData setup
import CoreData

class CoreDataManager {
    static let shared = CoreDataManager()
    
    lazy var persistentContainer: NSPersistentContainer = {
        let container = NSPersistentContainer(name: "DataModel")
        container.loadPersistentStores { _, error in
            if let error = error {
                fatalError("CoreData error: \(error)")
            }
        }
        return container
    }()
    
    var context: NSManagedObjectContext {
        return persistentContainer.viewContext
    }
    
    func saveContext() {
        if context.hasChanges {
            try? context.save()
        }
    }
}




When to Use CoreData

  • Complex relational data
  • Large datasets
  • Need for queries and filtering
  • Data synchronization requirements

3. Keychain - Secure Storage

// Keychain wrapper
class KeychainManager {
    static let shared = KeychainManager()
    
    func save(key: String, data: Data) -> Bool {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: key,
            kSecValueData as String: data
        ]
        
        SecItemDelete(query as CFDictionary)
        return SecItemAdd(query as CFDictionary, nil) == errSecSuccess
    }
    
    func load(key: String) -> Data? {
        let query: [String: Any] = [
            kSecClass as String: kSecClassGenericPassword,
            kSecAttrAccount as String: key,
            kSecReturnData as String: true
        ]
        
        var item: CFTypeRef?
        if SecItemCopyMatching(query as CFDictionary, &item) == errSecSuccess {
            return item as? Data
        }
        return nil
    }
}




When to Use Keychain

  • Passwords and authentication tokens
  • Sensitive user data
  • Cryptographic keys
  • Data that should survive app deletion

4. SwiftData - Modern Data Persistence

// SwiftData model
import SwiftData

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

// SwiftData usage
struct ContentView: View {
    @Environment(\.modelContext) private var context
    @Query private var users: [User]
    
    var body: some View {
        List(users) { user in
            Text(user.name)
        }
        .onAppear {
            addUser()
        }
    }
    
    private func addUser() {
        let newUser = User(name: "John", email: "john@example.com")
        context.insert(newUser)
        try? context.save()
    }
}




When to Use SwiftData

  • SwiftUI applications
  • Modern iOS development (iOS 17+)
  • Type-safe data modeling
  • Replacing CoreData in new projects

Decision Matrix

Storage Method Use Case Data Size Security
UserDefaults Settings, preferences Small (<1MB) Low
CoreData Complex relational data Large Medium
Keychain Sensitive data Small High
SwiftData Modern SwiftUI apps Medium-Large Medium