Что такое персистентность данных в iOS-разработке?

«Что такое персистентность данных в iOS-разработке?» — вопрос из категории Базы данных, который задают на 10% собеседований IOS Разработчик. Ниже — развёрнутый ответ с разбором ключевых моментов.

Ответ

Персистентность данных — это способность приложения сохранять своё состояние (данные, настройки) между запусками, после перезагрузки устройства или даже после удаления и повторной установки приложения (если данные синхронизированы с облаком).

Основные способы хранения данных в iOS:

Способ Для чего используется Ключевые особенности
UserDefaults Небольшие простые данные: настройки, флаги, счётчики. Быстро, просто. Не для чувствительных или больших данных.
Файловая система (FileManager) Документы, изображения, аудио, любые пользовательские файлы. Прямой доступ к файлам. Использует песочницу приложения.
Keychain Services Чувствительные данные: пароли, токены, сертификаты. Безопасное зашифрованное хранилище. Сохраняется между установками.
Core Data Сложные объектные графы, реляционные данные, с большими наборами. Объектно-графовый фреймворк. SQLite "под капотом". Мощные запросы.
SQLite (через обёртки) Прямая работа с реляционной БД. Полный контроль над SQL. Требует знания SQL.
Realm Альтернатива Core Data для объектного хранения. Простой API, высокая производительность.

Примеры кода:

1. UserDefaults:

// Запись
UserDefaults.standard.set("John", forKey: "userName")
UserDefaults.standard.set(true, forKey: "isOnboardingCompleted")
// Чтение
let name = UserDefaults.standard.string(forKey: "userName")
let isCompleted = UserDefaults.standard.bool(forKey: "isOnboardingCompleted")

2. Файловая система (сохранение Data):

func saveDataToFile(_ data: Data, fileName: String) -> URL? {
    guard let documentsDir = FileManager.default.urls(for: .documentDirectory, 
                                                     in: .userDomainMask).first else {
        return nil
    }
    let fileURL = documentsDir.appendingPathComponent(fileName)
    do {
        try data.write(to: fileURL)
        return fileURL
    } catch {
        print("Ошибка сохранения: (error)")
        return nil
    }
}

3. Keychain (используя библиотеку KeychainAccess для простоты):

import KeychainAccess
let keychain = Keychain(service: "com.yourapp.bundleid")
// Сохранить токен
keychain["authToken"] = "eyJhbGciOiJ..."
// Прочитать токен
let token = keychain["authToken"]

Критерии выбора:

  • Объём данных: Маленький (UserDefaults) vs. Большой (Core Data/Файлы).
  • Структура: Простые типы vs. Сложные объектные связи.
  • Безопасность: Keychain для секретов.
  • Необходимость в запросах: Core Data/SQLite для сложной фильтрации и сортировки.
  • Производительность и простота использования.