Category的底层分析之initialize

31 篇文章 0 订阅

这篇博客我们将围绕这几个问题来探究initialize.

1.+initialize方法详解

2.load、initialize方法的区别是什么?它们在category中的调用顺序?以及出现继承时他们之间的调用过程?

首先看我的截图,我们先看一下initialize会不会像load一样,runtime加载类、分类的时候就会调用.

还是一样,我创建GDPerson类和Test1、Test2分类,里面分别调用了initialize方法,如下:

从这可以看出,initialize并没有调用,这里我们都能分辨出initialize和load调用机制都不一样(不了解load的请看我上一篇博客Category的底层分析之load),我先直接说一个结论:

+initialize方法会在类第一次接收到消息的时候调用

下面我们先用代码验证,比如我先给GDPerson发alloc [GDPerson alloc];我们看一下结果

细心的可能发现,这里是不是和我们之前的类方法调用非常像,其实是一样的,它也是通过消息机制来发送的类似objc_msgSend([GDPerson class],@selector(initialize)),根据我们之前的知识知道,如果类和分类方法同名,优先调用分类的方法,而且是后编译的先调用一摸一样(大家可以自己尝试上面的代码,后面我会证明),接下来我们看一下.

如果出现继承会怎么样?

我再创建一个GDStudent的类,里面同样打印GDStudent+initialize,我们看看结果:

initialize调用的时候会优先调用父类的initialize,再调用子类的initialize,而且先初始化父类,再初始化子类,每个类只会初始化一次

+initialize有可能会调用多次的情况

现在我再创建GDCat的子类,继承GDStudent,然后把GDStudent里面的+(void)initialize删除,我们再运行一下看看会出现什么情况.

父类的是被调用了多次,也很清楚是为什么,GDStudent在初始化的时候会调用+initialize,它就会来到我们之前学习的,先通过isa找到GDStudent的元类对象,在元类对象找+initialize,发现找不到,就会通过superclass找父类GDPerson的元类对象,再去找发现找到了,所以就打印了2次.这里我们又知道initialize的另外一种情况

源码分析

(之前好几篇博客都是有介绍源码下载地址)

首先我们想既然是在发消息的时候调用+initialize方法,所以我们去源码看看objc_msgSend方法有没有介绍+initialize的情况.

这里发现点进去全是汇编语言,汇报语言就不浪费大家时间,我们通过另一个思路去想,class_getInstanceMethod方法去查看,我看了最新版的源码是objc4-818版本,它里面不像之前的版本可以看出一些实现,而objc4-818版本我看多数实现是汇编语言,所以无法具体分析,这里大家可以下载一个之前的版本分析,都是非常清楚的,我把源码分析步骤发一下,有兴趣的可以尝试一下

(如果后面有可以看出的,我会补充上).

总结:

1.+initialize方法详解

1.+initialize方法会在类第一次收到信息时调用

2.先调用父类的+initialize,再调用子类的+initialize(先初始化父类,再初始化子类,每个类只会初始化一次)

3.如果子类没有实现+initialize,会调用父类的+initialize (所以父类的+initialize 可能会被调用多次)

4.如果分类实现了+initialize,就会覆盖类本身的+initialize调用

2.load、initialize方法的区别是什么?

1.load是根据函数地址直接调用,initialize是通过objc_msgSend调用(调用方式上)

2.load是在runtime加载类、分类的时候调用(只会调用1次),而initialize是在第一次接收到消息的时候调用,每个类只会initialize一次,父类的initialize可能被执行多次(调用时刻上)

3.load:先调用类的,调用子类之前会先调用父类,先编译的类,优先调用,

然后再调用分类的,也是先编译的分类优先调用;

initialize:先初始化父类,再初始化子类,可能是多次调用父类的initialize.(调用顺序上)

接下来博客我会介绍iOS关联对象的底层知识.

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

  • 4
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值