这个包最初的目的是编写一个访问 UserDefaults
的属性包装器。然而,由于我希望避免处理非直接属性列表可转换类型的所有开销,它很快就超越了最初的目的。
@UserDefault("hasSeenSplashScreen") var hasSeenSplashScreen = false
@UserDefault("name") var name: String?
@UserDefault("count") var count: Int? = 42
hasSeenSplashScreen = true
name = "John Appleseed"
count = nil
对于 Codable
,有一个协议扩展,可以让你避免编写那些样板代码。
struct CodableStruct {
var foo: String
}
extension CodableStruct: Equatable, Codable, DefaultsValueConvertible {}
@UserDefault("test") var test = CodableStruct(foo: "hello, world!")
test.foo = "goodbye."
以及对于 NSCoding
。
extension UIColor: DefaultsValueConvertible {}
@UserDefault("color") var color = UIColor.systemRed
color = .systemBlue
我不会在这里深入细节,但也存在针对 Array
、Dictionary
、Collection
、Optional
和 RawRepresentable
的条件一致性(使其易于使用枚举)。目标是涵盖标准库中的所有合理情况,因此如果您发现缺少某些内容,请打开一个 issue 或 PR!
您可以直接使用 plist 兼容的值
struct Convertible {
var name: String
}
extension Convertible: DefaultsValueConvertible {
typealias DefaultsRepresentation = String
init(defaultsRepresentation: String) throws {
name = defaultsRepresentation
}
func defaultsRepresentation() throws -> String {
name
}
}
或者将该操作委托给另一个符合 DefaultsValueConvertible
的类型。
struct IndirectConvertible {
var name: String
}
extension IndirectConvertible: IndirectDefaultsValueConvertible {
typealias DefaultsRepresentation = Convertible.DefaultsRepresentation
init(indirectRepresentation: Convertible) throws {
name = indirectRepresentation.name
}
func indirectRepresentation() throws -> Convertible {
try .init(defaultsRepresentation: name)
}
}
plist 兼容的类型(如 Bool
、Data
、String
等)符合 DefaultsValue
协议,该协议建立了与 UserDefaults
之间的编码和解码。
@UserDefault
属性包装器适用于任何符合 DefaultsValueConvertible
的类型,该类型编码为符合 DefaultsValue
的关联类型,并从默认值中存储和加载。(DefaultsValue
本身也符合此协议,因此您可以将其与包装器一起使用。)
如果您希望委托给另一个 DefaultsValueConvertible
类型,而不是直接使用 plist 兼容类型,您可以改为符合 IndirectDefaultsValueConvertible
(它继承自前者),允许您编码为任何 DefaultsValueConvertible
类型和从中解码。这意味着您可以拥有任意长度的编码/解码委托链,而无需编写太多样板代码。
如果您正在处理类似序列的类型,那么最好的选择可能是符合 ExpressibleByArray
或 ExpressibleBySequence
,这将允许您避免将元素映射到/从其默认表示形式的样板代码,前提是您可以从 Array
或任何 Sequence
初始化自己。