关键词
Swift 反射 Mirror
Representation of the sub-structure and optional "display style" of any arbitrary subject instance.Describes the parts---such as stored propertIEs,collection elements,tuple elements,or the active enumeration case---that make up a particular instance. May also supply a "display style" property that suggests how this structure might be rendered.
/// A collection of `Child` elements describing the structure of the/// reflected subject.public let children: Children/// Suggests a display style for the reflected subject.public let displayStyle: Mirror.displayStyle?@warn_unused_resultpublic func superclassMirror() -> Mirror?
children记录了该object下的变量(注:此处object为广义的定义)
displayStyle表示该object的类型(同上)
superclassMirror,顾名思义,表示其父类的Mirror
public enum displayStyle { case Struct case Class case Enum case Tuple case Optional case Collection case Dictionary case Set }
根据displayStyle的类型去判断类型再做分类讨论,其中Optional是Swift中独有比较特别的类型,需要特殊处理,当displayStyle为nil时,表示为基本数据类型
最后通过superclassMirror一层一层递归,去遍历所有变量
func getModel(dic:Dictionary<String,Any>,objname:String) -> MYDataModel { let modelClass = NSClassFromString(objname) as! MYDataModel.Type model = modelClass.init() var mirror:Mirror? = Mirror(reflecting: model) while (mirror != nil) { traverseProperty(dic,mirror,model) mirror = mirror!.superclassMirror() } return model }private func traverseProperty(dic:Dictionary<String,_ mirror:Mirror?,_ model:MYDataModel) { if (mirror == nil) { return } else { for (_,value) in mirror!.children.enumerate() { let propertyname:String = value.label == nil ? "" : value.label! let properValue = value.value let dictionaryValue = dic[propertyname] let tmp = Mirror(reflecting: properValue) if (dictionaryValue != nil) { if (tmp.displayStyle != nil) { switch tmp.displayStyle! { case .Class: if let dicValue = dictionaryValue as? [String: String] { let anyClass = model.classForCoder as? NSObject.Type let arrayTypename = anyClass!.performSelector(Selector("\(propertyname)Type")).takeRetainedValue() as? String let anyArrayClass = NSClassFromString(arrayTypename!) as! MYDataModel.Type let obj = anyArrayClass.init() traverseProperty(dicValue,Mirror(reflecting: obj),obj) model.setValue(obj,forKey: propertyname) } case .Collection: let anyClass = model.classForCoder as? NSObject.Type let arrayTypename = anyClass!.performSelector(Selector("\(propertyname)Type")).takeRetainedValue() as? String switch arrayTypename! { case MYDataModelType.String.rawValue: if let arrayValue = dictionaryValue as? [String] { if (arrayValue.count > 0) { model.setValue(arrayValue,forKey: propertyname) } } default: if let arrayValue = dictionaryValue as? [[String: String]] { var resultArray = [(NSClassFromString(arrayTypename!) as! MYDataModel.Type).init()] for item in arrayValue { let anyArrayClass = NSClassFromString(arrayTypename!) as! MYDataModel.Type let obj = anyArrayClass.init() traverseProperty(item,obj) resultArray.append(obj) } model.setValue(resultArray,forKey: propertyname) } break } case .Dictionary: print("Dictionary") case .Optional: if (tmp.children.count > 0) { for (_,value2) in tmp.children.enumerate() { let properValue2 = value2.value switch properValue2 { case _ as Bool: if let boolValue = dictionaryValue as? Bool { model.setValue(NSNumber(bool:boolValue),forKey: propertyname) } case _ as Int: if let intValue = dictionaryValue as? Int { model.setValue(NSNumber(integer: intValue),forKey: propertyname) } case _ as float : if let floatValue = dictionaryValue as? float { model.setValue(NSNumber(float: floatValue),forKey: propertyname) } case _ as Double : if let doubleValue = dictionaryValue as? Double { model.setValue(NSNumber(double: doubleValue),forKey: propertyname) } case _ as String: if let stringValue = dictionaryValue as? String { model.setValue(stringValue,forKey: propertyname) } default: print("\(propertyname) is an unkown optional value") break } } } else { print("\(propertyname) is an unkown value") if let objValue = dictionaryValue as? AnyObject { model.setValue(objValue,forKey: propertyname) } } default: break } } else { switch properValue { case _ as Bool: if let boolValue = dictionaryValue as? Bool { model.setValue(NSNumber(bool:boolValue),forKey: propertyname) } case _ as Int: if let intValue = dictionaryValue as? Int { model.setValue(NSNumber(integer: intValue),forKey: propertyname) } case _ as float : if let floatValue = dictionaryValue as? float { model.setValue(NSNumber(float: floatValue),forKey: propertyname) } case _ as Double : if let doubleValue = dictionaryValue as? Double { model.setValue(NSNumber(double: doubleValue),forKey: propertyname) } case _ as String: if let stringValue = dictionaryValue as? String { model.setValue(stringValue,forKey: propertyname) } default: break } } } } } }
源码地址:https://github.com/VictorWuSH/SwiftExercise
总结以上是内存溢出为你收集整理的Swift中的反射全部内容,希望文章能够帮你解决Swift中的反射所遇到的程序开发问题。
如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。
欢迎分享,转载请注明来源:内存溢出
评论列表(0条)