Подклассы UserDefaults - PullRequest
0 голосов
/ 13 июня 2018

tldr;почему мы всегда используем UserDefaults.standard вместо того, чтобы создавать подклассы UserDefaults для создания чего-то, что более точно соответствует нашим потребностям?

Кто-нибудь когда-либо имел подклассы UserDefaults?Или это считается плохой практикой?

Скажем, например, что мы делаем подкласс ColorDefaults класса UserDefaults.Когда приложение, объект ColorDefaults создается, и этот объект загружает все свои собственные данные.И загруженные данные могут затем быть отправлены в соответствующий объект посредством делегирования или сделаны универсально доступными через синглтон.

Моя теория работы заключается в том, что UserDefaults предназначен только для хранения относительно большого количества данных, поэтому необходимо использоватьСинглтон реализует эту идею.

Итог: используем ли мы UserDefaults.standard, потому что:

  1. подклассы не одобряются
  2. мы должны избегать слишком большой экономииданные для UserDefaults в целом
  3. в любом случае подклассификация не имеет большого значения?
  4. почти что-нибудь еще.

Ответы [ 3 ]

0 голосов
/ 13 июня 2018

Кажется, вы ищете что-то вроде этого

class ColorDefaults : NSObject
{
    /// Save Data
    class func saveDataInDefaultForKey(_ key: String, _ data: Any){
        UserDefaults.standard.set(data, forKey: key)
    }

    /// Retrieve data
    class func retrieveDataFromDefaultsWithKey(_ key: String) -> Any {
        return UserDefaults.standard.value(forKey: key) as Any
    }
}

Сохраните и получите данные:

/// Save Data
ColorDefaults.saveDataInDefaultForKey("myArray", myArray)
ColorDefaults.saveDataInDefaultForKey("myString", myString)

/// Get Data
if let valueString = ColorDefaults.retrieveDataFromDefaultsWithKey("myString") as? String {
        print("Saved Value String: \(valueString)")
 }
 else {
        print("Error retrieving myString")
 }

 if let valueArray = ColorDefaults.retrieveDataFromDefaultsWithKey("myArray") as? [String] {
        print("Saved Value Array: \(valueArray)")
 }
 else{
        print("Error retrieving myArray")
 }

Вывод:

enter image description here

0 голосов
/ 13 июня 2018

Пользовательские настройки по умолчанию - это система хранения файлов.Существует мало смысла в создании подклассов, если вы не хотите изменить его логику.Но вы можете создать несколько мастей, таких как UserDefaults(suiteName: String).Что вы ожидаете от подклассов?Вы можете просто глобально определить let myDefaults = UserDefaults(suiteName: String) и использовать его где угодно.Я думаю, вы могли бы использовать такие методы, как

class MyDefaults: UserDefaults {

    func saveName(_ name: String) {
        setValue(name, forKey: "name_key")
    }

}

Но с другой стороны, может иметь смысл создать расширение

extension UserDefaults {
    func saveName(_ name: String) {
        setValue(name, forKey: "name_key")
    }
}

или сделать его немного более сложным:

extension UserDefaults {

    struct User {
        static let defaults = UserDefaults(suiteName: "User")
        static func saveName(_ name: String) {
            defaults.setValue(name, forKey: "name")
        }
    }

    struct General {
        static let defaults = UserDefaults.standard
        static func saveLastOpened(date: Date) {
            defaults.setValue(date, forKey: "last_opened")
        }
    }

}

Но все они имеют один фатальный поток: теперь вы зависите от использования пользовательских настроек по умолчанию в приложении.В какой-то момент может возникнуть необходимость сохранить эти данные в другой форме, например в локальном файле JSON, синхронизированном с iCloud.Я думаю, что UserDefaults.User можно изменить, чтобы сделать это, но это будет очень уродливо.Мы хотим не UserDefaults.User.saveName("My name"), а User.saveName("My name").С точки зрения интерфейса нам не важно, где будет сохранено это имя пользователя, и если будет введена новая система для сохранения этих данных, нам не нужно изменение интерфейса.

Другими словами, представьте, что вы используете UserDefaults.User.saveName на 100 мест в вашем приложении и теперь хотите использовать другую систему для сохранения имени пользователя.Теперь вам нужно изменить код на 100 мест, чтобы использовать AnotherSystem.User.saveName, в то время как если вы просто используете User.saveName, интерфейс все еще действителен.

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

0 голосов
/ 13 июня 2018

Ваш ColorDefaults не должен быть подклассом UserDefaults.Это должна быть простая структура или класс с вычисленными свойствами, которые поддерживаются UserDefaults.

Вот пример, использующий статические свойства, но вы можете изменить его, чтобы использовать вместо него класс singleton.

struct ColorDefaults {
    static var someDefault: String {
        get {
            return UserDefaults.standard.string(forKey: "someKey") ?? "some initial value"
        }
        set {
            UserDefaults.standard.set(newValue, forKey: "someKey")
        }
    }
}

let someVal = ColorDefaults.someDefault // read
ColorDefaults.someDefault = "hello" // write

Это также было бы полезно, если бы одно из ваших значений по умолчанию было более сложным и нуждалось в кодировании / декодировании для UserDefaults.Логика используется здесь и не распространяется на все ваше приложение.

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

...