Runtime 消息机制: 程序启动时,首先加载运行时,是OC的底层
应用场景:
1. 关联对象 -> (给分类动态添加属性时简单提到过一次)
2. 交换方法 -> (换肤时介绍过)
3. 动态获取对象属性
前两种使用场景之前简单提到过,这里来说一下动态获取对象属性的使用场景
为了演示动态获取对象属性:
- 我定义了一个Person类,声明了两个属性" name 和 age ";
- 创建一个NSObject+Runtime分类,提供一个方法来获取类的属性列表
+ (NSArray *)js_objProperties;
3.在ViewController中导入Person类和NSObject+Runtime,使用分类方法实例化对象属性列表并打印结果
Person类中,只声明了两个属性:
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic,copy) NSString *name;
@property (nonatomic,assign) NSInteger age;
@end
NSObject+Runtime中
.h
#import <Foundation/Foundation.h>
@interface NSObject (Runtime)
// 获取类的属性列表数组
+ (NSArray *)js_objProperties;
@end
.m中
#import "NSObject+Runtime.h"
#import <objc/runtime.h>
@implementation NSObject (Runtime)
+ (NSArray *)js_objProperties{
/*
class_copyIvarList(__unsafe_unretained Class cls, unsigned int *outCount) 成员变量
class_copyMethodList(__unsafe_unretained Class cls, unsigned int *outCount) 方法
class_copyPropertyList(__unsafe_unretained Class cls, unsigned int *outCount) 属性
class_copyProtocolList(__unsafe_unretained Class cls, unsigned int *outCount) 协议
*/
/* 调用运行时方法,取得类的属性列表
返回值 : 所有属性的数组 (是一个C数组指针:C语言中数组的名字就是首元素的地址)
参数 1 : 要获取的类
参数 2 : 类属性的个数指针
*/
unsigned int count = 0;
objc_property_t *propertyList = class_copyPropertyList([self class], &count);
// 用来存放所有属性的数组
NSMutableArray *mArr = [NSMutableArray array];
// 遍历所有属性
for (unsigned int i = 0; i < count; i ++) {
// 1. 从数组中取得所有属性
objc_property_t property = propertyList[i];
const char *cName = property_getName(property);
NSString *propertyName = [NSString stringWithCString:cName encoding:NSUTF8StringEncoding];
[mArr addObject:propertyName];
}
// C语言中 retain/create/copy 都需要release, 可以option+click方法名,通过API描述中找到释放方法 ( 例如这里的提示: You must free the array with free().)
free(propertyList);
return mArr.copy;
}
@end
控制器中
#import "ViewController.h"
#import "Person.h"
#import "NSObject+Runtime.h"
@interface ViewController ()
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
NSArray *properties = [Person js_objProperties];
NSLog(@"%@",properties);
}
@end
这样就实现了动态获取对象属性
打印信息:
2016-08-11 12:03:50.053 动态获取对象属性[11372:900458] (
name,
age
)