Mirror

作者: 吕建雄 | 来源:发表于2021-08-11 12:16 被阅读0次

    Mirror 

    反射:是指可以动态获取属性、成员信息,在运行时可以调用方法、属性等行为的特性

     Swift并不像OC那样,Swift是静态语言(OC支持runtime动态操作),在使用OC时很少强调反射概念,因为OC的Runtime要比其他语言中的反射强大的多。

     Swift标准库提供了反射机制(Mirror),用来访问成员信息(对于函数是没法进行访问的,如果需访问,需要将函数定义为属性信息)

    enum LTSeasonEnum {

        case FIRST,SECOND,THIRD,FORTH

    }

    class LTMirror: NSObject{

        var age:Int=18

        var season: LTSeasonEnum = .FIRST

        func printSeason(){

            print("************")

        }

    }

    let mirror =Mirror(reflecting:LTMirror.self)

    for c in mirror.children{

        print("\(c.label ??"0"):\(c.value)")

    }

    运行上面代码,没有任何打印。因为Mirror中传入的参数不对,应该是传入实例对象

    let mir = LTMirror()

    let mirror2 =Mirror(reflecting:mir.self)

    for c in mirror2.children{

        //通过label输出当前的名称,value输出当前反射的值

        print("\(c.label ??"0"):\(c.value)")

    }

    运行上述代码输出:

    age:18

    season:FIRST

    标准库提供了反射机制来访问成员信息;Swift基于Mirror的结构体来实现,可以通过为具体的实例创建一个Mirror对象,然后就可以通过它查询这个实例

    进入到源码(Mirror.swift),看Mirror的定义

    Mirror init

    Mirror的init方法,传入的是一个Any类型

    children

    children其实是一个AnyCollection,接收一个泛型

    Child,是一个元祖类型,由可选标签和值构成

    通过源码可知通过label、value能打印出名称和value的原因。

    即可以在编译时期且不用知道任何类型信息情况下,在Child的值上用Mirror去遍历整个对象的层级视图

    根据Mirror的特性,可以通过Mirror做JSON解析

    class LTMirrorJson{

        var age: Int = 18

        var name: String = "TOTTI"

    }

    func formatJson(_ object: Any) -> Any{

        let mirror =Mirror(reflecting: object)

        guard !mirror.children.isEmpty else{

            return object

        }

        var keyValue: [String:Any] = [:]

        for child in mirror.children{

            if let keyName = child.label{

                keyValue[keyName] =formatJson(child.value)

            }else{

                print("child")

            }

        }

        return keyValue

    }

    let mj = LTMirrorJson()

    print(formatJson(mj))

    上述代码,运行结果为:["age": 18, "name": "TOTTI"]

    上面代码只是针对LTMirrorJson的JSON解析,为了方便其他类使用,可以将Json解析抽取称一个协议,然后提供一个默认实现,让类遵守协议

    //定义一个JSON解析协议

    protocol LTGeneralJSONMap{

        func formatJson() ->Any

    }

    //提供一个默认实现

    extension LTGeneralJSONMap{

        func formatJson() ->Any{

            let mirror =Mirror(reflecting:self)

            guard  !mirror.children.isEmpty else{

                return self

            }

            //定义用于存储json数据的字典

            var jsonMap: [String:Any] = [:]

            for child in mirror.children{

                if let value = child.value as? LTGeneralJSONMap{

                    if let key = child.label {

                        jsonMap[key] = value.formatJson()

                    }else{

                        print("error key is nil")

                    }

                }else{

                    print("the json protocol is not implement")

                }

            }

            return jsonMap

        }

    }

    上述代码实现了通用的json解析,如果使用的话,只需实现LTGeneralJSONMap协议即可

    class LTJsonClass: LTGeneralJSONMap{

        var age:Int=18

        var name: String = "TOTTI"

    }

    var jc = LTJsonClass()

    print(jc.formatJson())

    运行输出:

    the json protocol is not implement

    the json protocol is not implement

    [:]

    并不是我们想象中的结果,原因是类中属性的类型也需要遵守LTGeneralJSONMap协议

    增加如下代码

    extension Int: LTGeneralJSONMap{}

    extension String: LTGeneralJSONMap{}

    输出结果如下:

    ["age": 18, "name": "TOTTI"]

    相关文章

      网友评论

          本文标题:Mirror

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