Swift中的反射

来源:互联网 发布:华为mate7root软件 编辑:程序博客网 时间:2024/05/17 08:11

关键词

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, Any>, _ 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, Mirror(reflecting: obj), 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

0 0
原创粉丝点击