官方api说明
主要分为以下小类:
1.Working with Classes 和类相关,主要包括获取类名,给类增加属性,获取类信息,类相关的增删查改。
2.Adding Classes 增加一个类。
3.Working with Instances
4.Obtaining Class Definitions
5.Working with Instance Variables
6.Associative References
7.Working with Methods 和方法相关,可以解答为什么调用一个nslog会导致主线程休眠。(func method_exchangeImplementations(Method!, Method!)
Exchanges the implementations of two methods.)
8.Working with Selectors
9.Working with Protocols
10.Working with Properties
11.Working with Properties
平常用的比较多的事1和7,详细介绍下。
消息转发三部曲
接下来的内容都和消息转发有关, 所以有必要先简单介绍一下OC的消息转发机制:
- (BOOL)resolveInstanceMethod:(SEL)sel
当向对象发送消息而对象没有对应的实现时, 消息会通过+(BOOL)resolveInstanceMethod:方法询问具体的接收类: 没有实现的话, 你能不能现在造一个实现出来?
通常现场造出消息实现都是走的class_addMethod添加对应的实现, 然后回答YES, 那么此次消息发送算是成功的, 否则进入下一步.
- (id)forwardingTargetForSelector:(SEL)aSelector
上一步没有结果的话消息会进行二次询问: 造不出来没关系, 你告诉我谁有这个消息的对应实现? 我去它那找也行的.
此时如果返回一个能响应该消息的对象, 那么消息会转发到返回对象那里, 如果返回nil或者返回对象不能相应此消息, 进行最后一步.
- (void)forwardInvocation:(NSInvocation *)anInvocation
到了这一步, 消息发送其实算是失败了, 不会再有询问过程, 而是直接将消息携带的一切信息包裹在NSInvocation中交给对象自己处理. 另外, forwardInvocation:在构造Invocation时会调用methodSignatureForSelector:获取方法签名, 所以一般情况下还需要实现这个方法返回相应的方法签名.
此时如果对象拿到invocation中的信息有能力发起[Invacation invoke], 那么消息对应的实现还是能正常进行, 只是相对于正常的发送过程稍微麻烦耗时些, 否则就会触发消息不识别的异常返回.
理解了消息转发,开始说runtime能做的事情:
1.获取
获取类名,获取成员变量,获取成员属性,获取实例方法,获取协议列表。
2,方法修改
动态加载方法,方法交换
3.属性关联。