← Назад к вопросам

Какие типы данных можно сохранить в UserDefaults?

1.0 Junior🔥 251 комментариев
#Хранение данных#Язык Swift

Комментарии (1)

🐱
deepseek-v3.2PrepBro AI5 апр. 2026 г.(ред.)

Ответ сгенерирован нейросетью и может содержать ошибки

Основные типы данных для UserDefaults

UserDefaults — это легковесное хранилище ключ-значение, предназначенное для сохранения небольших объемов данных: настроек приложения, состояния UI, флагов и простых пользовательских данных. Оно автоматически сериализует объекты в plist (Property List) формат, что накладывает ключевое ограничение: сохраняемый объект должен быть совместим с Property List.

Нативные типы Property List (Foundation Types)

Следующие типы из Foundation нативно поддерживаются и могут быть сохранены напрямую:

  • String и NSString
  • Int, Float, Double, Bool и их Objective-C аналоги (NSNumber)
  • Data и NSData (универсальный контейнер для бинарных данных)
  • Date и NSDate
  • Array ([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, который внутри преобразует его.

Важные практические замечания

  1. Объем данных: UserDefaults не предназначен для больших данных (изображений, каталогов). Используйте для этого файловую систему, Core Data или базы данных.
  2. Безопасность: Не храните в UserDefaults конфиденциальную информацию (пароли, токены). Для этого используйте Keychain Services.
  3. Синхронизация: При включении App Groups и использовании UserDefaults(suiteName:) данные можно синхронизировать между расширениями (extensions) и основным приложением.
  4. iCloud/Кросс-платформенная синхронизация: Для автоматической синхронизации настроек между устройствами через iCloud используется NSUbiquitousKeyValueStore, который имеет схожий API, но еще более строгие лимиты по объему и частоте записи.

Итог: В UserDefaults можно напрямую сохранять базовые типы Property List (String, Number, Data, Date, Array, Dictionary). Все сложные объекты необходимо предварительно сериализовать, преимущественно с помощью протокола Codable, в тип Data. Выбор этого хранилища должен быть осознанным и соответствовать его назначению — хранению простых пользовательских настроек и состояния приложения.