前言
在开发中有时候有的类我们只能看到.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在这里下载
总结
以上就是对获取成员变量和属性的方法的总结。写的不好请大家多多指教。
网友评论