RunTime
RunTime入门教程,强力推荐: Objective-C Runtime 1小时入门教程
RunTime补充: Objective-C特性:Runtime
RunTime补充1: 理解 Objective-C Runtime
RunTime补充2: Objective-C Runtime
RunTime收尾: 刨根问底Objective-C Runtime
Objective-C 中的对象本质上是结构体对象,其中 isa 是它唯一的私有成员变量。
实例方法是保存在类中的,而类方法是保存在元类中的。
原则上,方法的名称 name 和方法的实现 imp 是一一对应的,而 Method Swizzling 的原理就是动态地改变它们的对应关系,以达到替换方法实现的目的。
+load vs +initialize
+load 方法是当类或分类被添加到 Objective-C runtime 时被调用的,实现这个方法可以让我们在类加载的时候执行一些类相关的行为。子类的 +load 方法会在它的所有父类的 +load 方法之后执行,而分类的 +load 方法会在它的主类的 +load 方法之后执行。但是不同的类之间的 +load 方法的调用顺序是不确定的
如果子类没有实现 +load 方法,那么当它被加载时 runtime 是不会去调用父类的 +load 方法的。同理,当一个类和它的分类都实现了 +load 方法时,两个方法都会被调用。因此,我们常常可以利用这个特性做一些“邪恶”的事情,比如说方法混淆(Method Swizzling)。
其实load调用有两种情况:
类被加载到runtime的时候,runtime会自动先后调用主类和分类的load方法,调用方式是通过直接获取函数指针的进行调用,因此两个都会调用;
第二种情况:手动调用主类的load方法:[ClassA load],这种调用方法是通过消息发送进行调用的,需要遍历主类的方法列表,找到对应函数进行调用。然而此时,分类的load方法已经嵌入到主类的方法列表中,造成覆盖,因此会实际调用的是分类的load方法。+initialize 方法是在类或它的子类收到第一条消息之前被调用的,这里所指的消息包括实例方法和类方法的调用。也就是说 +initialize 方法是以懒加载的方式被调用的
runtime 使用了发送消息 objc_msgSend 的方式对 +initialize 方法进行调用。也就是说 +initialize 方法的调用与普通方法的调用是一样的,走的都是发送消息的流程。换言之,如果子类没有实现 +initialize 方法,那么继承自父类的实现会被调用;如果一个类的分类实现了 +initialize 方法,那么就会对这个类中的实现造成覆盖。
如果我们想确保自己的 +initialize 方法只执行一次,避免多次执行可能带来的副作用时,我们可以使用下面的代码来实现:
(+) (void)initialize {
if (self == [ClassName self]) {
// ... do the initialization ...
}
| +load | +initialize
---- | ---- | ----
调用时机 | 被添加到 runtime 时 | 收到第一条消息前,可能永远不调用
调用顺序 |父类->子类->分类 |父类->子类
调用次数 |1次 |多次
是否需要显式调用父类实现 |否 |否
是否沿用父类的实现 |否 |是
分类中的实现 |类和分类都执行 |覆盖类中的方法,只执行分类的实现
XMPP
** XMPP基础-by:简书 - 侯垒 **
** XMPP协议原理-by:CSDN - imyfriend**
** iOS开发之使用XMPPFramework实现即时通信-by:伯乐在线 - 青玉伏案**
** XMPP 协议适合用来做移动 IM 么 -by:segmentfault - 丰俊文**
** iOS开发即时通讯环境搭建-XMPP -by:简书 - CoderQiao **
** 微信、陌陌等著名IM软件设计架构详解-by:jinglijun **