看了onevcat的文章,觉得看了一遍什么都没记住,然后似乎又都理解了。这种感觉非常好,然后就playground中操作了一遍。原链接onevcat
Mirror最基本的用法我们都相对比较了解。
struct Cat:Dictionaryable{
var name:String
var age:Int
}
let cat = Cat(name: "onevcat", age: 20)
let mirror = Mirror(reflecting: cat)
for child in mirror.children {
print(child.label,child.value)
}
通过这种方式我们可以通过反射打印出对象中所有的属性信息
我们可以自定义一个协议,通过协议拓展的方式返回给我们要的Any
protocol Dictionaryable{
var value:Any{get}
}
然后给一些基础的数据类型默认实现
extension Int:Dictionaryable{ var value: Any{return self}}
extension Double:Dictionaryable{ var value: Any{return self}}
extension Bool:Dictionaryable{ var value: Any{return self}}
extension String:Dictionaryable{ var value: Any{return self}}
通过协议拓展的方式,让满足它的其他类型通过Mirror的方式构建字典
extension Dictionaryable{
var value:Any{
//1.获取Mirror
//2.mirror的children
//3.把mirror中的label和value拼起来
//4.考虑异常的情况
let mirror = Mirror(reflecting: self)
var dict:[String:Any] = [:]
for item in mirror.children {
guard let label = item.label else { fatalError("Invalid key in child:key\(item)") }
if let value = item.value as? Dictionaryable{
dict[label] = value.value
}else{
fatalError("Invalid value in child:value\(item)")
}
}
return dict
}
}
此时自定义一个struct遵循Dictionaryable,会发现可以打印出对应的dict。
struct Person:Dictionaryable{
var name:String
var cat:Cat
}
let person = Person(name: "@David", cat: cat)
print(person.value)
有对象嵌套也可以,因为刚才的取得是item.value.value。如果item.value自身是自定义类型的话,会发生具体方法的调用最后返回拼接好的dict。
当然此时无法完成Array和Dictionary的转换。此时我们要加入Array和Dictionary的拓展
Swift4.1之后已经支持协议拓展,对拓展对象中的泛型进行约束。
extension Dictionary: DictionaryValue where Value: DictionaryValue
{
var value: Any { return mapValues { $0.value } }
}
extension Array:Dictionaryable where Element:Dictionaryable{
var value:Any{
return ({$0.value})
}
}
但是在之前的版本还不行,我们没有办法对拓展类型中的泛型进行约束。我们需要在返回的方法调用中进行强制转换。
extension Array:Dictionaryable{
var value:Any{
return map({($0 as! Dictionaryable).value})
}
}
extension Dictionary:Dictionaryable{
var value:Any{
return mapValues({$0 as! Dictionaryable}).value
}
}
完成之后我们就可以进行Array和Dictionary的转换了。