美文网首页runtime
runtime遍历所有属性

runtime遍历所有属性

作者: 轻云绿原 | 来源:发表于2018-10-01 11:23 被阅读16次

    这段时间做征收平台项目,其中有个需求是比较两个类之间所有的属性是否相等,前几天做的是如下

    class A:NSObject {
        var a:String
        var b:Int
        var c:Date
        .
        .
        .
        //有几十个var,要疯了
    
        static func == (lhs:A,rhs:A) -> Bool {
            return lhs.a == rhs.a && lhs.b == rhs.b && lhs.c == rhs.b ....//好无聊阿,浪费时间
        }
    }
    

    大问题:是这样的class, 有几十个......

    有没有其它方法,可以懒一些,

    runtime

    思路

    我们可以用runtime遍历这样的类的属性,再把属性值给取出来做比较.

    0. 原料:

    class TestObj:NSObject {
        var str:String = "string"
        var number:Int = 34343
        var date:Date = Date()
        var list:[String] = ["d","f"]
        
        init(date:Date) {
          self.date = date
          super.init()
        }
    }
    

    1.首先要把类中的属性拿出来

    var count:UInt32 = UInt32.max  //这里用来保存类中有几个可拿的属性
    let firstPropertyPointer = class_copyPropertyList(TestObj.self,&count)
    // firstPropertyPointer,就是数组一样指向第一个属性的地址
    

    把count 打印出来看看.
    然后看到的是

    "0" .....

    咋回事?
    原来是runtime只在objective-c里生效,那把所有属性加上@objc

    class TestObj:NSObject {
        @objc var str:String = "string"
        @objc var number:Int = 34343
        @objc var date:Date = Date()
        @objc var list:[String] = ["d","f"]
        
        init(date:Date) {
          self.date = date
          super.init()
        }
    }
    

    再打印count看一下,
    现在看到

    "4"

    正常了.

    2.可以遍历一样属性了,看看

    for i in 0 ..< count {
        let pointer  = firstPropertyPointer.advanced(by:Int(i))//得到属性的指针(地址)
        let property = pointer.move()//得到property,(地址指向的值)
        let name = String(cString:property_getName(property))//得到属性的名字
    }
    

    这样就可以打印出这个类里标有@objc的所有属性的名字了

    3.再向下就是得到值了

    let obj = TestObj(date:Date())
    obj.value(forKey:name)
    

    4.比较

    let value = obj.value(forKey:name)
    

    这个value出来的是Any?,不能直接比较.所有objective-C里的都是类,是类就是继承至NSObject,那这样的话就可以如下写

    let value = obj.value(forKey:name) as! NSObject
    

    5.综合

    class TestObj: NSObject {
         @objc var obj:String = "fd"
         @objc var number:Int = 12312
         @objc var date:Date = Date()
         @objc var list:[String] = ["d","f"]
        
        init(date:Date){
            super.init()
            self.date = date
        }
        static func == (lhs:TestObj,rhs:TestObj) -> Bool{
            var count:UInt32 = UInt32.max
            guard let firstPropertyPointer = class_copyPropertyList(TestObj.self, &count) else{
                return false
            }
            for i in 0 ..< count {
                let propertyP = firstPropertyPointer.advanced(by: Int(i))
                let property = propertyP.move()
                let propertyName = String(cString:property_getName(property))
                let lValue = lhs.value(forKey: propertyName) as! NSObject
                let rValue = rhs.value(forKey: propertyName) as! NSObject
                if lValue != rValue {
                    return false
                }
            }
            free(firstPropertyPointer)//释放内存,这是C语言层面的,不会自动释放内存
            return true
        }
    }
    

    相关文章

      网友评论

        本文标题:runtime遍历所有属性

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