Какие типы данных можно сохранить в UserDefaults?
Комментарии (1)
Ответ сгенерирован нейросетью и может содержать ошибки
Основные типы данных для UserDefaults
UserDefaults — это легковесное хранилище ключ-значение, предназначенное для сохранения небольших объемов данных: настроек приложения, состояния UI, флагов и простых пользовательских данных. Оно автоматически сериализует объекты в plist (Property List) формат, что накладывает ключевое ограничение: сохраняемый объект должен быть совместим с Property List.
Нативные типы Property List (Foundation Types)
Следующие типы из Foundation нативно поддерживаются и могут быть сохранены напрямую:
StringиNSStringInt,Float,Double,Boolи их Objective-C аналоги (NSNumber)DataиNSData(универсальный контейнер для бинарных данных)DateиNSDateArray([Any]) иNSArray— при условии, что все элементы массива сами являются plist-совместимыми типами.Dictionary([String: Any]) иNSDictionary— при условии, что ключи являютсяString, а значения — plist-совместимыми типами.
Пример прямого сохранения нативных типов:
let defaults = UserDefaults.standard
// Простые значения
defaults.set("Иван", forKey: "userName")
defaults.set(25, forKey: "userAge")
defaults.set(true, forKey: "isOnboardingCompleted")
// Коллекции
defaults.set(["русский", "английский"], forKey: "supportedLanguages")
defaults.set(["score": 100, "level": 5], forKey: "gameState")
Типы, требующие преобразования (Archive & Encode)
Пользовательские типы (struct, class, enum) и другие неподдерживаемые нативно коллекции (например, Array<CGPoint>) не могут быть сохранены напрямую. Для их сохранения необходимо преобразовать их в поддерживаемый тип, чаще всего в Data.
1. Сериализация через Codable (Рекомендуемый современный способ)
Тип должен соответствовать протоколу Codable. Используются JSONEncoder/JSONDecoder или PropertyListEncoder/PropertyListDecoder.
struct UserSettings: Codable {
var theme: String
var volume: Double
var notificationsEnabled: Bool
}
let settings = UserSettings(theme: "dark", volume: 0.8, notificationsEnabled: true)
// Сохранение
do {
let encodedData = try JSONEncoder().encode(settings)
defaults.set(encodedData, forKey: "userSettings")
} catch {
print("Ошибка кодирования: \(error)")
}
// Загрузка
if let savedData = defaults.data(forKey: "userSettings") {
do {
let decodedSettings = try JSONDecoder().decode(UserSettings.self, from: savedData)
} catch {
print("Ошибка декодирования: \(error)")
}
}
2. Архивация через NSKeyedArchiver (Унаследованный способ, в основном для Objective-C или NSCoding типов)
Тип должен наследоваться от NSObject и соответствовать протоколу NSCoding (или NSSecureCoding).
class GameScore: NSObject, NSSecureCoding {
static var supportsSecureCoding: Bool = true
var score: Int
init(score: Int) { self.score = score }
required init?(coder: NSCoder) {
score = coder.decodeInteger(forKey: "score")
}
func encode(with coder: NSCoder) {
coder.encode(score, forKey: "score")
}
}
let highScore = GameScore(score: 9999)
let archivedData = try NSKeyedArchiver.archivedData(withRootObject: highScore, requiringSecureCoding: true)
defaults.set(archivedData, forKey: "highScore")
Типы, которые НЕЛЬЗЯ сохранить напрямую
Следующие типы не являются plist-совместимыми и вызовут исключение при попытке сохранения без преобразования:
- Пользовательские классы/структуры, не реализующие
Codable/NSCoding. - Сложные коллекции с неподдерживаемыми элементами (напр.,
Set<UIColor>). - Нескалярные типы C и Core Graphics:
CGPoint,CGRect,CGSize. UIImage/NSImage(требует преобразования вData, например, черезpngData()илиjpegData(compressionQuality:)).URLсохраняется, но не напрямую как объект URL.UserDefaultsимеет специальный методset(_:forKey:)дляURL, который внутри преобразует его.
Важные практические замечания
- Объем данных:
UserDefaultsне предназначен для больших данных (изображений, каталогов). Используйте для этого файловую систему,Core Dataили базы данных. - Безопасность: Не храните в
UserDefaultsконфиденциальную информацию (пароли, токены). Для этого используйте Keychain Services. - Синхронизация: При включении App Groups и использовании
UserDefaults(suiteName:)данные можно синхронизировать между расширениями (extensions) и основным приложением. - iCloud/Кросс-платформенная синхронизация: Для автоматической синхронизации настроек между устройствами через iCloud используется
NSUbiquitousKeyValueStore, который имеет схожий API, но еще более строгие лимиты по объему и частоте записи.
Итог: В UserDefaults можно напрямую сохранять базовые типы Property List (String, Number, Data, Date, Array, Dictionary). Все сложные объекты необходимо предварительно сериализовать, преимущественно с помощью протокола Codable, в тип Data. Выбор этого хранилища должен быть осознанным и соответствовать его назначению — хранению простых пользовательских настроек и состояния приложения.