Что такое персистентность данных в 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 для сложной фильтрации и сортировки.
  • Производительность и простота использования.

Ответ 18+ 🔞

А, слушай, про персистентность! Ну это ж, блядь, самая соль, когда твоё приложение не обосрётся и не забудет всё, как только пользователь его закроет. Представь: зашёл, настроил, вышел — а нахуй, опять логиниться? Пиздец, пользователь снесёт приложение к ебеням.

Вот тебе, сука, шпаргалка, как эту самую память устроить, чтобы всё помнилось. Выбирай по обстоятельствам, а то накосячишь — будешь потом как Герасим, с мешком на озере стоять.

Основные конторы для хранения добра:

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

Ну и примерчики, чтобы не быть просто пиздаболом:

1. UserDefaults (для ленивых):

// Запихнули
UserDefaults.standard.set("Василий", forKey: "userName")
UserDefaults.standard.set(true, forKey: "isOnboardingCompleted")
// Достали
let name = UserDefaults.standard.string(forKey: "userName")
let isCompleted = UserDefaults.standard.bool(forKey: "isOnboardingCompleted")

Вот, видишь? Ничего сложного. Но если сюда массив из 10 000 объектов сунешь — приложение будет запускаться как черепаха в сиропе.

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, а то там свой API — просто пиздец):

import KeychainAccess
let keychain = Keychain(service: "com.yourapp.bundleid")
// Спрятали токен
keychain["authToken"] = "eyJhbGciOiJ..."
// Достали токен
let token = keychain["authToken"]

Вот это уже серьёзно. Это уже не просто файлик, это, блядь, сейф. Для паролей и прочей конфиденциальной хуйни.

Как же выбрать, ёпта?

  • Сколько вешать в граммах? Мало — UserDefaults. Много — Core Data или файлы.
  • Что за структура? Просто число/строка или сложная сеть объектов, которые друг друга ебут?
  • А безопасность? Если это пароль — только Keychain, иначе ты, прости, мудак.
  • Нужны ли сложные выборки? Типа «покажи всех пользователей из Москвы, купивших синий ковёр после вторника» — тогда Core Data или SQLite.
  • Не хочешь ебаться? Выбирай самое простое, что решает задачу. Не гонись за модным, если можно обойтись UserDefaults.

Вот и вся магия. Главное — не храни пароли в UserDefaults, а то потом будешь как тот чувак, который ключи от сейфа на видное место кладёт. Удачи, не обосрись.