Swift 结构扩展

Swift Struct extension

我有一个设置结构,它在 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)
    }
}

 ....
 ....
}

我想延长它。我想在对等设备上获取应用程序 运行 的另一个实例的设置并将其存储为 DictionarymySetting 必须 return 来自 dictionary 而不是 UserDefaults 的 key.mySetting key 的值。但是如果没有连接对等设备,那么它应该return UserDefaults.

中的值

我想知道如何扩展 Settings 结构(或者在需要时将其更改为 class)来实现此功能,而无需在代码中的数百个位置放置 'if then else'。

我在数百个地方这样做:

 var settings = Settings()

 let settings = Settings()

一些能够自动提取正确的设置字典来查找的构造是最好的。

编辑:正如我所说,并非所有 return 类型都可以很简单,这使得工作变得更加困难。有些 return 类型是枚举,有些是字典,有些是数组。正如一些人建议使用一种 returns Any? 的统一方法一样,例如,在我使用 return 类型的地方,这项工作会更加困难。

  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)
    }
}

我会为字典添加一个可选的 属性,然后使用一对 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)
}