Ответ
Данные, хранящиеся в песочнице приложения (UserDefaults, Documents, Caches), удаляются вместе с приложением. Для сохранения данных между установками необходимо использовать внешние или системные хранилища.
1. Keychain (Связка ключей iCloud)
Назначение: Безопасное хранение чувствительных данных (токены, пароли, сертификаты). Сохранение между установками: Да, если включена синхронизация с iCloud Keychain.
import Security
func saveTokenToKeychain(_ token: String) -> Bool {
let data = token.data(using: .utf8)!
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "userAuthToken",
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
kSecValueData as String: data,
// Ключ для синхронизации через iCloud Keychain
kSecAttrSynchronizable as String: true
]
SecItemDelete(query as CFDictionary) // Удалить старую запись
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
2. iCloud Drive / CloudKit
Назначение: Хранение пользовательских документов и структурированных данных в облаке. Сохранение между установками: Да, данные привязаны к Apple ID.
3. Удаленный сервер (Backend)
Назначение: Централизованное хранение всех пользовательских данных. Сохранение между установками: Да, при условии аутентификации пользователя (логин/пароль, Sign in with Apple). Это самый надежный и контролируемый способ.
4. App Groups (UserDefaults & File Container)
Назначение: Общее хранилище для нескольких приложений одного разработчика. Сохранение между установками: Нет. Данные в App Group удаляются, когда удаляется последнее приложение в группе. Не является решением для сохранения после удаления одного целевого приложения.
Сравнение методов
| Метод | Тип данных | Требует сети | Безопасность | Рекомендация |
|---|---|---|---|---|
| Keychain + iCloud | Токены, пароли | Нет (синхронизация фоновая) | Очень высокая | Для аутентификационных данных |
| iCloud Drive | Документы, файлы | Да (для загрузки) | Высокая | Для пользовательских файлов |
| Удаленный сервер | Любые данные | Да | Зависит от реализации | Для основного контента приложения |
Best Practice: Используйте комбинацию:
- Keychain для хранения сессионного или refresh-токена.
- При первом запуске после переустановки проверяйте Keychain на наличие токена.
- Если токен найден — автоматически входите в аккаунт и загружайте основные данные с сервера.
- Для пользовательских файлов предлагайте сохранение в iCloud Drive.
Ответ 18+ 🔞
Да ты посмотри, какие мы тут хитрые схемы придумываем! Сидит разработчик, чешет репу, и думает: "Ну как же так, блядь, пользователь удалил приложение, а теперь орет, что все его данные нахуй пропали!". А я ему говорю — так и должно быть, ёпта! Песочница она на то и песочница, чтобы после удаления замка — весь песок выметали. UserDefaults, Documents, Caches — всё это летит в тартарары вместе с иконкой с рабочего стола.
Но если тебе реально надо, чтобы данные пережили даже самый жесткий пользовательский "забей и удали", то вот тебе, дружок, рабочие варианты, без этой твоей высосанной из пальца хуйни.
1. Keychain (она же Связка, она же iCloud Keychain)
Зачем: Чтобы спрятать самое ценное — пароли, токены доступа, всякую такую пиздецово важную хрень. Переживет переустановку?: Да, блядь! Если, конечно, у чела включена синхронизация связки с iCloud. А она у 99% включена.
import Security
func saveTokenToKeychain(_ token: String) -> Bool {
let data = token.data(using: .utf8)!
let query: [String: Any] = [
kSecClass as String: kSecClassGenericPassword,
kSecAttrAccount as String: "userAuthToken",
kSecAttrAccessible as String: kSecAttrAccessibleAfterFirstUnlock,
kSecValueData as String: data,
// Вот эта волшебная строка говорит: "синхронизируй это говно через iCloud"
kSecAttrSynchronizable as String: true
]
SecItemDelete(query as CFDictionary) // Выковыриваем старую запись, если была
let status = SecItemAdd(query as CFDictionary, nil)
return status == errSecSuccess
}
2. iCloud Drive / CloudKit
Зачем: Для документов, настроек, каких-то структурных данных — чтобы у пользователя всё было под рукой на всех его яблочных железяках. Переживет переустановку?: Абсолютно. Данные-то в облаке висят, привязанные к Apple ID, а не к конкретной копии приложения.
3. Удаленный сервер (Твой бэкенд)
Зачем: Для всего, блядь, остального! Основной профиль, контент, история, сохраненки. Центр управления полетами. Переживет переустановку?: Это самый живучий вариант, ёпта. Удалил сто раз приложение — зашел по логину/паролю или через Sign in with Apple, и все твои котики и достижения на месте. Но без сети — пиши пропало.
4. App Groups (UserDefaults & File Container)
Зачем: Чтоб несколько твоих приложений могли совать нос в одну общую миску. Переживет переустановку?: Вообще-то нет, блядь! Это частая ошибка. Данные в App Group удалятся, когда пользователь сотрет с устройства последнее приложение из этой группы. Так что если он удалит только твое основное приложение, а твой же виджет оставит — то да, данные могут сохраниться. Но рассчитывать на это — играть в русскую рулетку.
Короче, табличка для наглядности
| Метод | Что храним | Нужен интернет? | Надежность | Когда юзать |
|---|---|---|---|---|
| Keychain + iCloud | Токены, пароли, ключи | Нет (синхронизируется сама) | Выше крыши | Для всего, что связано с доступом к аккаунту |
| iCloud Drive | Документы, файлы пользователя | Да (чтобы подтянуть) | Высокая | Если приложение работает с файлами (типа редактор) |
| Удаленный сервер | Всё, что угодно | Обязательно | Зависит от тебя | Для основного контента и данных приложения |
Идеальная схема, чтобы не быть мудаком:
- В Keychain суешь refresh-токен. Пользователь переустановил приложение — токен на месте.
- При первом запуске лезешь в Keychain. Токен есть? Отлично, ебёшь им сервер и получаешь новый сессионный токен и все данные пользователя.
- Пользователь автоматом внутри аккаунта, даже пароль вводить не надо. Волшебство, блядь!
- Для тяжелых файлов даешь опцию "Сохранить в iCloud". И все довольны.
Вот и вся магия, а не "ой, у меня все пропало".