Swift Utilities — Упрощаем работу с UserDefaults

от автора

За годы работы разработчиком iOS, я собрал множество инструментов и полезных штук, которые облегчают процесс разработки. В этой статье, я хочу поделиться одним из таких инструментов. Это будет не большая статья. Я покажу, как пользоваться этой утилитой, продемонстрирую её в действии. Надеюсь, что статья окажется полезной для вас.

Работа с UserDefaults может быть удобной и простой, в этом поможет обертка UserDefaultsWrapper. Давайте разберемся, как она работает.

UserDefaultsWrapper – это свойство-обертка (property wrapper), которое облегчает сохранение и извлечение данных из UserDefaults. Он особенно полезен, когда вы работаете с типами данных, такими как URL, массивы, словари, примитивные типы (String, Int, Bool и т.д.).

import Foundation  /// - Parameters: ///   - key: Data will be saved and extracted using this key ///   - defaultValue: This value will be substituted when there is no value ///   - userDefaults: NSUserDefaults is a hierarchical persistent interprocess (optionally distributed) key-value store, optimized for storing user settings. /// /// Types an UserDefaultsWrapper can work with: ///``` ///  URL? ///  [Any]? ///  [String : Any]? ///  String? ///  [String]? ///  Data? ///  Bool ///  Int ///  Float ///  Double /// ``` /// /// - Warning: ///  If the type is not optional, default == nil will cause a crash. /// /// Exemple: /// ``` /// class User { /// ///    @UserDefaultsWrapper<String>(key: "FirstName", default: "John") var firstName ///    @UserDefaultsWrapper(key: "LastName", default: "John") var lastName: String /// ///    // OR /// ///    @UserDefaultsWrapper(key: "Age") var age: Int? ///    @UserDefaultsWrapper(key: "Old", default: 6) var old: Int? /// } /// /// let user = User() /// print(user.firstName) // John /// user.firstName = "Misha" /// print(user.firstName) // Misha /// $user.firstName.removeObject() /// /// print(user.old) // optional(6) /// user.old = 18 /// print(user.old) // optional(18) /// user.old = nil /// print(user.old) // optional(6) /// /// print(user.age) // nil /// user.age = 18 /// print(user.age) // optional(18) /// user.age = nil /// print(user.age) // nil /// ``` @propertyWrapper public struct UserDefaultsWrapper<T> {     private let key: String     private let defaultValue: T!     private let userDefaults: UserDefaults      public var wrappedValue: T {         get {             let anyValue = userDefaults.value(forKey: key)             let value: T = (anyValue as? T) ?? defaultValue             return value         }         set {             if let optional = newValue as? AnyOptional, optional.isNil {                 userDefaults.removeObject(forKey: key)                  if let defaultValue = defaultValue {                     self.set(newValue: defaultValue)                 }             } else {                 self.set(newValue: newValue)             }             userDefaults.synchronize()         }     }      public var projectedValue: ActionUserDefault { self }      /// - Parameters:     ///   - key: Data will be saved and extracted using this key     ///   - defaultValue: This value will be substituted when there is no value     ///   - userDefaults: NSUserDefaults is a hierarchical persistent interprocess (optionally distributed) key-value store, optimized for storing user settings.     ///     /// - Warning:     ///  If the type is not optional, default == nil will cause a crash.     public init(key: String, default defaultValue: T? = nil, userDefaults: UserDefaults = .standard) {         self.key = key         self.userDefaults = userDefaults         self.defaultValue = defaultValue     }      private func set(newValue: T) {         userDefaults.setValue(newValue, forKey: key)     } }  // MARK: - ActionUserDefault  extension UserDefaultsWrapper: ActionUserDefault {      public func removeObject() {         userDefaults.removeObject(forKey: key)          if let defaultValue = defaultValue {             self.set(newValue: defaultValue)         }     } }  // MARK: - Helper classes  private protocol AnyOptional {     var isNil: Bool { get } }  extension Optional: AnyOptional {     var isNil: Bool { self == nil } }  public protocol ActionUserDefault {     func removeObject() } 

Использование

Пример использования UserDefaultsWrapper может выглядеть так:

class User {        @UserDefaultsWrapper<String>(key: "FirstName", default: "John") var firstName     @UserDefaultsWrapper(key: "LastName", default: "John") var lastName: String       @UserDefaultsWrapper(key: "Age") var age: Int?     @UserDefaultsWrapper(key: "Old", default: 6) var old: Int? }

Здесь firstName, lastName , Age и Old – это свойства, которые автоматически сохраняют свои значения в UserDefaults и извлекают их оттуда.

UserDefaultsWrapper также включает в себя метод removeObject(), который удаляет значение из UserDefaults и, при наличии, возвращает значение по умолчанию.

$user.firstName.removeObject()

Преимущества и Применение

UserDefaultsWrapper упрощает и делает более безопасным работу с UserDefaults. Он уменьшает повторяющийся код и предотвращает возможные ошибки, связанные с неправильным ключом при сохранении и извлечении данных. Используя этот подход, вы можете улучшить структуру и читаемость вашего кода.

Еще статьи Swift Utilities:


ссылка на оригинал статьи https://habr.com/ru/articles/774888/


Комментарии

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *