浅谈iOS中runtime
来源:互联网 发布:已婚网友见面目的知乎 编辑:程序博客网 时间:2024/06/06 08:56
一、runtime机制
runtime: 指一个程序在运行(或在被执行)的状态。也就是说,当你打开一个程序使它在电脑上运行的时候,那个程序就是处于运行时刻。在一些编程语言中,把某些可以重用的程序或者实例打包或者重建成为“运行库”。这些实例可以在他们运动的时候被连接或者被任何程序调用。
objective-C中runtime:是一套比较底层的纯C语言API,属于一个C语言库,包含了很多底层的C语言API。
在我们平时编写的OC代码在程序运行过程中都会转化成runtime的C语言代码执行,例如
[target doSomething];
, 会被转化成objc_msgSend(target,@selector(doSomething));
。OC中一切都被设计成了对象,我们都知道一个类被初始化成一个实例,这个实例是一个对象,实际上一个类的本质上也是以一个对象,在runtime中用结构体表示。
(见上一篇【类的本身也是一个对象—-isa指针详解】相关的定义:
/// 描述类中的一个方法typedef struct objc_method *Method;/// 实例变量typedef struct objc_ivar *Ivar;/// 类别Categorytypedef struct objc_category *Category;/// 类中声明的属性typedef struct objc_property *objc_property_t;
二、runtime的应用
1. 获取列表
有时候我们会需要获取当前类中每个属性的名字(比如字典转模型,字典的key和模型对象的属性名字不匹配)。
我们可以通过runtime的一些列方法获取类的一些信息(包括属性列表,方法列表,成员变量列表和遵循的协议列表)。
unsigned int count; //获取属性列表 objc_property_t *propertyList = class_copyPropertyList([self class], &count); for (unsigned int i=0; i<count; i++) { const char *propertyName = property_getName(propertyList[i]); NSLog(@"property---->%@", [NSString stringWithUTF8String:propertyName]); } //获取方法列表 Method *methodList = class_copyMethodList([self class], &count); for (unsigned int i; i<count; i++) { Method method = methodList[i]; NSLog(@"method---->%@", NSStringFromSelector(method_getName(method))); } //获取成员变量列表 Ivar *ivarList = class_copyIvarList([self class], &count); for (unsigned int i; i<count; i++) { Ivar myIvar = ivarList[i]; const char *ivarName = ivar_getName(myIvar); NSLog(@"Ivar---->%@", [NSString stringWithUTF8String:ivarName]); } //获取协议列表 __unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count); for (unsigned int i; i<count; i++) { Protocol *myProtocal = protocolList[i]; const char *protocolName = protocol_getName(myProtocal); NSLog(@"protocol---->%@", [NSString stringWithUTF8String:protocolName]); }
注:调用这些获取列表的方法别忘记导入头文件#import<objc/runtime.h>
。
2.方法调用
主要依靠isa指针((见上一篇【类的本身也是一个对象—-isa指针详解】)
- 如果用实例对象调用实例方法,会到实例的isa指针指向的对象(也就是类对象)操作。
- 如果调用的是类方法,就会到类对象的isa指针指向的对象(也就是元类对象)中操作。
1.首先,在相应操作的对象中的缓存方法列表中找调用的方法,如果找到,转向相应的实现并执行。
2.如果没找到,在相应操作的对象中的方法列表中找调用的方法,如果找到,转向相应实现执行。
3.如果没找到,去父类指针所指向的对象中执行1,2.
4.以此类推,如果一直到根类还没找到,转向拦截调用。
5.如果没有重写拦截调用的方法,程序报错。
3.拦截调用
拦截调用即在找不到调用的方法程序崩溃之前,可以通过重写以下几个方法来处理:
+ (BOOL)resolveClassMethod:(SEL)sel;+ (BOOL)resolveInstanceMethod:(SEL)sel;//后两个方法需要转发到其他的类处理- (id)forwardingTargetForSelector:(SEL)aSelector;- (void)forwardInvocation:(NSInvocation *)anInvocation;
4.动态添加方法
增加函数:class_addMethod
四个参数的意思分别是:
- Class cls 给哪个类添加方法,本例中是self
- SEL name 添加的方法,本例中是重写的拦截调用传进来的selector。
- IMP imp 方法的实现,C方法的方法实现可以直接获得。如果是OC方法,可以用+(IMP)instanceMethodForSelector:(SEL)aSelector;获得方法的实现。
- “v@:*”方法的签名,代表有一个参数的方法。
5.关联对象 (添加属性)
///设置关联对象objc_setAssociatedObject
四个参数的意思分别是:
1. id object 给谁设置关联对象
2. const void *key 关联对象唯一的key,获取时会用到
3. id value 关联对象
4. objc_AssociationPolicy 关联策略(属性修饰符枚举 )
//获取关联对象objc_getAssociatedObject
两个参数分别是:
- id object 获取谁的关联对象
- const void *key 根据这个唯一的key获取关联对象
6.方法交换
方法交换,即将两个方法的实现交换。例如,将A方法和B方法交换,调用A方法的时候,就会执行B方法中的代码,反之亦然。
交换两个方法的实现:method_exchangeImplementations.
替换类方法的定义:class_replaceMethod
设置一个方法的实现:method_setImplementation.
- 浅谈iOS中runtime
- iOS Runtime浅谈
- iOS之RunTime浅谈
- iOS-浅谈runtime运行时机制01
- iOS-浅谈runtime运行时机制02
- #转#iOS-浅谈runtime运行时机制
- iOS-浅谈runtime运行时机制01
- 浅谈iOS运行时机制runtime(1)
- 浅谈iOS运行时机制runtime(2)
- iOS-浅谈runtime运行时机制02-runtime简单使用
- iOS-浅谈runtime运行时机制02-runtime简单使用
- iOS-浅谈runtime运行时机制02-runtime简单使用
- iOS-浅谈runtime运行时机制02-runtime简单使用
- 浅谈runtime
- 浅谈Runtime
- iOS中runtime运行机制解析
- iOS中runtime运行机制解析
- iOS 中runtime进阶必备
- MAC设置HOST
- 每天一个 Linux 命令(16):which命令
- Java基础之IO流
- ionic1.3.1迄今为止遇到的bug
- (十八)VFS虚拟文件系统介绍、dup和dup2函数的介绍与使用
- 浅谈iOS中runtime
- Oracle 建立表空间和用户 \ 导出和导入 数据表
- Java应用一般架构
- 会场安排问题
- Partial Redundancy Elimination
- C语言基础(一)图形编程1
- Android控件构架与自定义控件详解(二)自定义View
- SDN之QoS--3:网络基础信息的测量(Floodlight)
- [年度计划]2017年年度学习规划