DependentMap
DependentMap 是一个 Swift 微框架,定义了一个从键到按键指定的类型的值的集合。
在 Swift 中,Dictionary<KeyType, ValueType> 是一个将键映射到值的集合。它是同质的,即所有键类型相同(此处为 KeyType),所有值类型相同(此处为 ValueType)。
通常有一些具有映射语义的类型,其中键类型都相同,但值类型不同。例如,考虑 UserDefaults。它可以让你用 String 键关联任意值。键关联的值类型取决于调用者。
UserDefaults.standard.set("Alice", forKey: "username")
UserDefaults.standard.set(Date(), forKey: "createDate")
let username = UserDefaults.standard.string(forKey: "username")
let createDate = UserDefaults.standard.object(forKey: "createDate") as? Date在此,我们在 username 键下添加了一个 String 值,并在 createDate 键下添加了一个 Date 值。但关联值的类型完全由约定定义。要读取它们,您需要知道 username 和 createDate 值的类型。您还需要使用 as? 构造来将 UserDefaults.object(forKey:) 返回的 Any 值转换为 Date 类型,该类型键所引用。
值类型与键关联,但这种类型是隐含的,对编译器来说是未知的。
这就是依赖映射的用途。依赖映射是一种将键映射到值的集合。它允许键指定它们可以关联的值的类型。
在我们的示例中,我们将创建两个键,即 username 和 createDate,并指定它们的关联值为类型 String 和 Date。
extension DependentMapKey {
static var username: DependentMapKey<UserDefaults, String, String> {
return .init("username")
}
static var createDate: DependentMapKey<UserDefaults, String, Date> {
return .init("createDate")
}
}DependentMapKey 声明具有三个类型参数的泛型
- 此键索引的依赖映射的类型。在上述两种情况下,此类型为
UserDefaults,表明这些键只能用于UserDefaults实例。 - 原始键类型。这是
String,因为UserDefaults使用String值作为键。将传递给计算属性体中init函数的原始值类型必须与此类型匹配。 - 此键参考的映射中的值的类型。
username键引用String值,而createDate键引用Date值。
然后我们可以使用这些键写入和读取 UserDefaults 对象
UserDefaults.standard.set("Alice", for: .username)
UserDefaults.standard.set(Date(), for: .createDate)
let username = UserDefaults.standard.value(for: .username)
let createDate = UserDefaults.standard.value(for: .createDate)在调用 set(_:for:) 的过程中,编译器确保值的类型与键声明的预期值类型相匹配。同样,编译器能够推断出通过 value(for:) 读取的值的类型,以满足键的声明。
详细信息
框架定义了一个 DependentMapSemantics 协议,该协议要求两个函数:value(for:) 和 set(_:for:),用于读取和写入与键关联的值。协议扩展定义了一个索引操作符,以便更简单地进行读取和写入访问。
框架还定义了一个 DependentMapKey<MapType, RawKeyType, ValueType> 类。其中 MapType 参数定义了该键可以用来定义 DependentMapSemantics 类型的类型。参数 RawKeyType 定义了底层集合中的键类型。《code WorthType 定义了键映射到的值类型。
提供了一个扩展到 Dictionary 以添加依赖关系映射语义。注意,此扩展的使用仅限于 Dictionary 实例,其中值为 Any。
最后,还提供了一个扩展到 UserDefaults 以添加依赖关系映射语义。