IOS 运行时(runtime)机制
1. 概述
OC 是一个全动态语言,OC 的一切都是基于 Runtime 实现的
只有在程序运行时,才会去确定对象的类型,并调用类与对象相应的方法`
2. 运行时机制
运行时机制是用 C++ 开发的,是一套苹果开源的框架
OC 是基于运行时开发的语言
3. 应用场景
运行时动态获取类的属性
主要应用:
- 字典转模型框架 MJExtension,JSONModel
- 利用
关联对象
为分类添加属性 - 利用
交换方法
拦截系统或其他框架的方法 - 误区:并不是使用的技术越底层,框架的效率就会越高
导入头文件
#import <objc/runtime.h>
4. 示例
为NSObject添加一个分类
//
// NSObject+Extension.m
//
#import "NSObject+Extension.h"
#import <objc/runtime.h>
@implementation NSObject (Extension)
const char *propertiesKey = "propertiesKey";
const char *methodsKey = "methodsKey";
const char *protocolKey = "protocolKey";
/// 字典转模型方法
+ (instancetype)objectWithDict:(NSDictionary *)dict
{
id obj = [[self alloc] init];
// 获取属性列表
NSArray *properties = [self propertyList];
// 遍历属性数组
for (NSString *key in properties)
{
// 判断字典中是否包含这个key
if (dict[key] != nil)
{
// 使用 KVC 设置属性值
[obj setValue:dict[key] forKeyPath:key];
}
}
return obj;
}
/**
如果能够自动生成这个数组,就好了!
如果要想动态的获取类的属性,需要使用到“运行时机制”
class_copyIvarList 成员变量,提示有很多第三方框架会使用 Ivar,能够获得更多的信息
但是:在 swift 中,由于语法结构的变化,使用 Ivar 非常不稳定,经常会崩溃!
class_copyPropertyList 属性
class_copyMethodList 方法
class_copyProtocolList 协议
*/
/// 返回类的属性列表
+ (NSArray *)propertyList
{
// 0. 判断是否存在关联对象, 如果存在, 直接返回
/** 参数
1> 关联到得对象
2> 关联的属性 key
*/
NSArray *plist = objc_getAssociatedObject(self, propertiesKey);
if (plist)
{
return plist;
}
// 1. 获取 ‘类的属性‘
/**
1> 类
2> 属性的计数指针
*/
unsigned int count = 0;
// 返回值是所有属性的数组 obj_property_
objc_property_t *list = class_copyPropertyList([self class], &count);
// 创建 存储属性数组
NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count; ++i)
{
// 获取属性
objc_property_t pty = list[i];
// 获取属性名
const char *cname = property_getName(pty);
[arrayM addObject:[NSString stringWithUTF8String:cname]];
}
// 释放属性数组
free(list);
// 设置关联对象
/**
1> 关联的对象
2> 关联对象的 key
3> 属性数值
4> 属性的持有方式 reatin, copy, assign
*/
objc_setAssociatedObject(self, propertiesKey, arrayM, OBJC_ASSOCIATION_COPY_NONATOMIC);
return arrayM.copy;
}
/// 返回类的方法列表
+ (NSArray *)methodList
{
// 0. 判断是否存在依赖关系
NSArray *mlist = objc_getAssociatedObject(self, methodsKey);
if (mlist)
{
return mlist;
}
unsigned int count = 0;
// 1. 获取方法列表
Method *list = class_copyMethodList([self class], &count);
// 存储方法数组
NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count; ++i)
{
// 获取方法
Method method = list[i];
// 获取方法名
SEL mname = method_getName(method);
[arrayM addObject: NSStringFromSelector(mname)];
}
// 释放数组
free(list);
// 设置依赖关系
objc_setAssociatedObject(self, methodsKey, arrayM, OBJC_ASSOCIATION_COPY_NONATOMIC);
return arrayM.copy;
}
/// 返回类的实现协议列表
+ (NSArray *)protocolList
{
// 0. 判断是否存在依赖关系
NSArray *pList = objc_getAssociatedObject(self, protocolKey);
if (pList)
{
return pList;
}
unsigned int count = 0;
// 2. 获取协议列表
Protocol * __unsafe_unretained *list = class_copyProtocolList([self class], &count);
// 创建协议数组
NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:count];
for (int i = 0; i < count; ++i)
{
// 获取协议
Protocol * __unsafe_unretained prot = list[i];
const char *pname = protocol_getName(prot);
[arrayM addObject:[NSString stringWithUTF8String:pname]];
}
return arrayM;
}
@end
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。