iOS 获取成员变量和属性

前言

在开发中有时候有的类我们只能看到.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 

@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 
#import 


@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 获取成员变量和属性)