美文网首页
iOS 获取成员变量和属性

iOS 获取成员变量和属性

作者: 不简单的风度 | 来源:发表于2017-06-07 17:19 被阅读607次

    前言

    在开发中有时候有的类我们只能看到.h文件,如果想看.m文件里的一些属性和方法就要用到runtime了,今天就来讨论下如何利用runtime获得某个类的成员变量和属性。

    成员变量

    定义

    成员变量定义如下:

    typedef struct objc_ivar *Ivar
    

    Ivar:是实例变量类型,是一个指向objc_ivar结构体的指针

    成员变量有如下相关函数:

    // 获取所有成员变量
    class_copyIvarList
    
    // 获取成员变量名
    ivar_getName
    
    // 获取成员变量类型编码
    ivar_getTypeEncoding
    
    // 获取指定名称的成员变量
    class_getInstanceVariable
    
    // 获取某个对象成员变量的值
    object_getIvar
    
    // 设置某个对象成员变量的值
    object_setIvar
    

    使用

    这里随便写一个model类
    model.h

    #import <Foundation/Foundation.h>
    
    @interface MM_Model : NSObject
    {
        NSString *_name;
    }
    
    @property (nonatomic, assign) NSInteger age;
    @property (nonatomic, assign) NSInteger score;
    @property (nonatomic, assign) BOOL      isAdult;
    
    @end
    

    model.m

    #import "MM_Model.h"
    #import <objc/runtime.h>
    #import <objc/message.h>
    
    
    @interface MM_Model ()
    
    @property (nonatomic, assign) NSInteger number;
    
    @end
    
    
    @implementation MM_Model
    
    
    - (void)sing{
        NSLog(@">>>>>sing");
    }
    
    - (void)say{
        NSLog(@">>>>>>>>say");
    }
    
    
    @end
    

    获取成员变量:

    /** 成员变量 */
    - (void)lyz_ivar{
        unsigned int outCount = 0;
        Ivar * ivars = class_copyIvarList([MM_Model class], &outCount);
        for (unsigned int i = 0; i < outCount; i ++) {
            Ivar ivar = ivars[i];
            const char * name = ivar_getName(ivar);
            const char * type = ivar_getTypeEncoding(ivar);
            NSLog(@"类型为 %s 的 %s ",type, name);
        }
        free(ivars);
        
    }
    

    打印结果如下:

    2017-06-07 17:04:00.691644+0800 runtimeDemo[454:49817] 类型为 @"NSString" 的 _name 
    2017-06-07 17:04:00.691728+0800 runtimeDemo[454:49817] 类型为 B 的 _isAdult 
    2017-06-07 17:04:00.691754+0800 runtimeDemo[454:49817] 类型为 q 的 _age 
    2017-06-07 17:04:00.691777+0800 runtimeDemo[454:49817] 类型为 q 的 _score 
    2017-06-07 17:04:00.691806+0800 runtimeDemo[454:49817] 类型为 q 的 _number 
    

    从打印结果可以看到无论是.h里声明的还是.m里声明的是都可以获取到的

    属性

    定义

    属性的定义:

    typedef struct objc_property *objc_property_t;
    

    objc_property_t是声明属性的类型,是一个指向objc_property结构体的指针

    相关函数如下:

    // 获取所有属性
    class_copyPropertyList
    
    // 获取属性名
    property_getName
    
    // 获取属性特性描述字符串
    property_getAttributes
    
    // 获取所有属性特性
    property_copyAttributeList
    

    使用

    /** 属性列表 */
    - (void)lyz_propery{
        unsigned int outCount = 0;
        objc_property_t * properties = class_copyPropertyList([MM_Model class], &outCount);
        for (unsigned int i = 0; i < outCount; i ++) {
            objc_property_t property = properties[i];
            //属性名
            const char * name = property_getName(property);
            //属性描述
            const char * propertyAttr = property_getAttributes(property);
            NSLog(@"属性描述为 %s 的 %s ", propertyAttr, name);
            
            //属性的特性
            unsigned int attrCount = 0;
            objc_property_attribute_t * attrs = property_copyAttributeList(property, &attrCount);
            for (unsigned int j = 0; j < attrCount; j ++) {
                objc_property_attribute_t attr = attrs[j];
                const char * name = attr.name;
                const char * value = attr.value;
                NSLog(@"属性的描述:%s 值:%s", name, value);
            }
            free(attrs);
            NSLog(@"\n");
        }
        free(properties);
    }
    

    打印结果如下:

    2017-06-07 17:09:24.816749+0800 runtimeDemo[461:51350] 属性描述为 Tq,N,V_number 的 number 
    2017-06-07 17:09:24.816829+0800 runtimeDemo[461:51350] 属性的描述:T 值:q
    2017-06-07 17:09:24.816862+0800 runtimeDemo[461:51350] 属性的描述:N 值:
    2017-06-07 17:09:24.816886+0800 runtimeDemo[461:51350] 属性的描述:V 值:_number
    2017-06-07 17:09:24.816936+0800 runtimeDemo[461:51350] 
    2017-06-07 17:09:24.816966+0800 runtimeDemo[461:51350] 属性描述为 Tq,N,V_age 的 age 
    2017-06-07 17:09:24.816994+0800 runtimeDemo[461:51350] 属性的描述:T 值:q
    2017-06-07 17:09:24.817021+0800 runtimeDemo[461:51350] 属性的描述:N 值:
    2017-06-07 17:09:24.817046+0800 runtimeDemo[461:51350] 属性的描述:V 值:_age
    2017-06-07 17:09:24.817062+0800 runtimeDemo[461:51350] 
    2017-06-07 17:09:24.817086+0800 runtimeDemo[461:51350] 属性描述为 Tq,N,V_score 的 score 
    2017-06-07 17:09:24.817110+0800 runtimeDemo[461:51350] 属性的描述:T 值:q
    2017-06-07 17:09:24.817133+0800 runtimeDemo[461:51350] 属性的描述:N 值:
    2017-06-07 17:09:24.817160+0800 runtimeDemo[461:51350] 属性的描述:V 值:_score
    2017-06-07 17:09:24.817176+0800 runtimeDemo[461:51350] 
    2017-06-07 17:09:24.817200+0800 runtimeDemo[461:51350] 属性描述为 TB,N,V_isAdult 的 isAdult 
    2017-06-07 17:09:24.817224+0800 runtimeDemo[461:51350] 属性的描述:T 值:B
    2017-06-07 17:09:24.817247+0800 runtimeDemo[461:51350] 属性的描述:N 值:
    2017-06-07 17:09:24.817292+0800 runtimeDemo[461:51350] 属性的描述:V 值:_isAdult
    2017-06-07 17:09:24.817308+0800 runtimeDemo[461:51350] 
    

    从打印结果可以看出这个方法无法获取成员变量,可以获取.h和.m里声明的属性。

    私有方法

    获取私有方法也是通过runtime,具体如下:

    /** 私有方法 */
    - (void)lyz_private{
        unsigned int count = 0;
        Method *memberFuncs = class_copyMethodList([MM_Model class], &count);//所有在.m文件显式实现的方法都会被找到
        for (int i = 0; i < count; i++) {
            SEL name = method_getName(memberFuncs[i]);
            NSString *methodName = [NSString stringWithCString:sel_getName(name) encoding:NSUTF8StringEncoding];
            NSLog(@"member method:%@", methodName);
        }
    }
    

    打印结果如下:

    2017-06-07 17:14:21.792194+0800 runtimeDemo[464:52108] member method:setIsAdult:
    2017-06-07 17:14:21.792271+0800 runtimeDemo[464:52108] member method:deleteUnderLine:
    2017-06-07 17:14:21.792350+0800 runtimeDemo[464:52108] member method:sing
    2017-06-07 17:14:21.792395+0800 runtimeDemo[464:52108] member method:say
    2017-06-07 17:14:21.792437+0800 runtimeDemo[464:52108] member method:isAdult
    2017-06-07 17:14:21.792461+0800 runtimeDemo[464:52108] member method:.cxx_destruct
    2017-06-07 17:14:21.792496+0800 runtimeDemo[464:52108] member method:description
    2017-06-07 17:14:21.792522+0800 runtimeDemo[464:52108] member method:setScore:
    2017-06-07 17:14:21.792566+0800 runtimeDemo[464:52108] member method:age
    2017-06-07 17:14:21.792602+0800 runtimeDemo[464:52108] member method:setAge:
    2017-06-07 17:14:21.792714+0800 runtimeDemo[464:52108] member method:score
    2017-06-07 17:14:21.792787+0800 runtimeDemo[464:52108] member method:number
    2017-06-07 17:14:21.792818+0800 runtimeDemo[464:52108] member method:setNumber:
    

    Demo在这里下载

    总结

    以上就是对获取成员变量和属性的方法的总结。写的不好请大家多多指教。

    参考

    明仔Su : iOS runtime实战应用:成员变量和属性

    相关文章

      网友评论

          本文标题:iOS 获取成员变量和属性

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