Swift中的反射

Swift中的反射,第1张

概述关键词 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 ele

关键词

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中的反射所遇到的程序开发问题。

如果觉得内存溢出网站内容还不错,欢迎将内存溢出网站推荐给程序员好友。

欢迎分享,转载请注明来源:内存溢出

原文地址: http://outofmemory.cn/web/1082469.html

(0)
打赏 微信扫一扫 微信扫一扫 支付宝扫一扫 支付宝扫一扫
上一篇 2022-05-27
下一篇 2022-05-27

发表评论

登录后才能评论

评论列表(0条)

保存