在Playground中尝试以下代码:
// make sure only `Optional` conforms to this protocolprotocol OptionalEquivalent { typealias WrappedValueType func toOptional() -> WrappedValueType?}extension Optional: OptionalEquivalent { typealias WrappedValueType = Wrapped // just to cast `Optional<Wrapped>` to `Wrapped?` func toOptional() -> WrappedValueType? { return self }}extension Dictionary where Value: OptionalEquivalent { func flatten() -> Dictionary<Key, Value.WrappedValueType> { var result = Dictionary<Key, Value.WrappedValueType>() for (key, value) in self { guard let value = value.toOptional() else { continue } result[key] = value } return result }}let a: [String: String?] = ["a": "a", "b": nil, "c": "c", "d": nil]a.flatten() //["a": "a", "c": "c"]因为您不能在
where协议扩展的子句中指定确切的类型,所以可以准确检测到该
Optional类型的一种方法是使
OptionalUNIQUELY符合协议(例如
OptionalEquivalent)。
为了获得的包装值类型
Optional,我
WrappedValueType在自定义协议中定义了typealias
OptionalEquivalent,然后对Optional进行了扩展,将assgin设置
Wrapped为
WrappedValueType,然后可以在flatten方法中获取类型。
注意,该
sugarCast方法只是将to强制转换
Optional<Wrapped>为
Wrapped?(这是完全相同的),以启用用法
guard语句。
更新
感谢Rob Napier的评论,我简化并重命名了sugarCast()方法,并重命名了协议以使其更易于理解。



