1.存放自定义数据
数据管理三把剑:
get、set、remove ,用key 来作为存取数据的凭证
2.类的方法动态实现机制
方法存储:
选择子,oc对象的方法可视为简单c函数,原型:
<return type>Class_selector(id self, SEL _cmd,...)
方法维护:
快速缓存表:存储选择子和方法的对应关系
方法调用:
objc_msgsend(some object,@selector(),parameters)去查找快速缓存表,涉及到消息转发
3.消息转发机制:(message forwarding)
三步分别是:说,这个是不是你的? --不是我啊
啊,不是?那你说是谁的?---是A的,
A没有这个啊 -- 那是B的(把东西改装了一下,写上了b的名字塞给了B)
对应:
1.+ resolveInstanceMethod:(SEL)sel // 对应实例方法
+ resolveClassMethod:(SEL)sel // 对应类方法
2.- (id)forwardingTargetForSelector:(SEL)aSelector
3.- (void)forwardInvocation:(NSInvocation *)anInvocation
具体用法见Runtime系列(消息转发)
4.runtime 用于hook等操作
用方法调配技术调试黑盒方法-method swizzling
Method m1 = class_getInstanceMethod([p1 class], @selector(printDZL));
Method m2 = class_getClassMethod([Person class], @selector(printDZ)); method_exchangeImplementations(m1, m2);
这样就能在自定义的方法里,hook 住黑盒中的代码
5.swift中的runtime
以下是一些结论:
- swift原生类没有runtime特性,纯Swift类的函数调用已经不再是OC的运行时发消息objc_msgsend,而是类似C++的vtable,在编译时就确定了调用什么函数,所以runtime获取不到,而继承NS0bject的类有
- 继承NS0bject的类如果返回值带有tuple等swift特性,则刚方法也失去动态派发
- @objc是用来将Swift的API导出给OC与OC runtime使用的,如果你继承NSObject的类,将会被自动的加入这个标识。可以在原生swift类里加上这个关键字赋予runtime特性
- 加了@objc标识的方法、属性都无法保证都会被运行时调用,因为Swift会做静态优化。所以非cocoa的原生方法,没办法保证动态派发特性,有可能会被静态优化,为了防止这种情况,可以在方法、属性前加上dynamic关键字
以上结论的详细解释见:Swift Runtime