美文网首页
Swift-Mirror类型转字典

Swift-Mirror类型转字典

作者: 沧州宁少 | 来源:发表于2018-03-17 19:03 被阅读0次

看了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的转换了。

相关文章

网友评论

      本文标题:Swift-Mirror类型转字典

      本文链接:https://www.haomeiwen.com/subject/yjgjqftx.html