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)
}
}
....
....
}
我想延长它。我想在对等设备上获取应用程序 运行 的另一个实例的设置并将其存储为 Dictionary
。 mySetting
必须 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)
}
我有一个设置结构,它在 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
必须 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)
}