Расширение Swift Struct - PullRequest
0 голосов
/ 15 июня 2019

У меня есть структура настроек, которая хранит сотни настроек в UserDefaults. Код ниже:

struct Settings {

public enum key: String
{
    case mySetting = "mySetting"
    ...
    ...

}

 public var mySetting: Bool {
    get {
        return UserDefaults.standard.bool(forKey: key.mySetting.rawValue)
    }

    set (newValue) {
        return UserDefaults.standard.set(newValue, forKey: key.mySetting.rawValue)
    }
}

 ....
 ....
}

Я хочу расширить его. Я хочу получить настройки другого экземпляра приложения, работающего на одноранговом устройстве, и сохранить его как Dictionary. mySetting должен вернуть значение key.mySetting key из этого dictionary, а не UserDefaults. Но если не подключено одноранговое устройство, оно должно вернуть значение в UserDefaults.

Мне интересно, как я могу расширить структуру «Настройки» (или, возможно, изменить ее на класс при необходимости), чтобы достичь этой функциональности, не помещая «если потом» в сотни мест в коде.

Я делаю это в сотнях мест:

 var settings = Settings()

или

 let settings = Settings()

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

Редактировать: Как я уже сказал, не все типы возвращаемых данных могут быть простыми, что усложняет работу. Некоторые возвращаемые типы: enum, словарь, Array. Так как некоторые предлагают иметь один унифицированный метод, который возвращает Any?, Работа будет труднее в местах, где я использую тип возврата, например.

  public var microphone: Microphone {
    get {
        if let mic = Microphone.init(rawValue: UserDefaults.standard.integer(forKey: key.microphone.rawValue)) {
            return mic
        } else {
            return .auto
        }
    }

    set (newValue) {
        UserDefaults.standard.set(newValue.rawValue, forKey: key.microphone.rawValue)
    }
}

1 Ответ

2 голосов
/ 15 июня 2019

Я хотел бы добавить свойство optinal для словаря, а затем, используя пару функций get и set, использовать словарь или UserDefaults

var peerDevice: [String: Any]?

func setting(forKey key: Key) -> Any? {
    if let dictionary = peerDevice {
        return dictionary[key.rawValue]
    }
    return UserDefaults.standard.value(forKey: key.rawValue)
}

mutating func set(_ value: Any, forKey key: Key) {
    if peerDevice != nil {
        peerDevice?[key.rawValue] = value
    } else {
        UserDefaults.standard.set(value, forKey: key.rawValue)
    }        
}

Пример метода-оболочки для перечислений с использованием необработанных значений

mutating func setEnum<T>(_ value: T, forKey key: Key) where T: RawRepresentable {
    set(value.rawValue, forKey: key)
}

func setting<T>(forKey key: Key, andEnumType: T.Type) -> T? where T: RawRepresentable {
    if let value = setting(forKey: key) as? T.RawValue {
        return T.init(rawValue: value)
    }
    return nil
}

Я позволил себе переименовать перечисление с key на Key

Тогда используйте это так

var settings = Settings()

settings.setSetting(true, forKey: .mySetting)

if let flag = settings.setting(forKey: .mySetting) as? Bool {
    print(flag)
}

settings.setEnum(Microphone.mic2, forKey: .mic)

if let mic = settings.setting(forKey: .mic, andEnumType: Microphone.self) {
    print(mic)
}
...