美文网首页
OC中load 和initialize 的区别

OC中load 和initialize 的区别

作者: Mrfang1 | 来源:发表于2020-09-28 20:31 被阅读0次

OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会有加载和初始化过程,这个过程就涉及到了类的两个类方法:loadinitialize。下面我们就来介绍一下这2个方法的区别。

1.load方法

1.1 调用时机

启动程序时,参与编译的类、分类会被加载进内存,load 方法就是在类被加载的时候调用的(前提是这个类有实现load方法)。

该方法的调用和这个类是否被使用无关,即使一个类在整个程序中都没有用到,也没有任何一个文件去引用该类的头文件,该类的load方法一样会被调用。

等所有类、分类都加载进内存后才会调用程序的main函数,所以所有类的load方法都是在main函数之前被调用的。而且每个类、分类的load方法都只会被调用一次

1.2 调用顺序

一个城西中如果所有的类、分类都实现了load方法,那么所有的load方法都会被调用。他们的执行顺序遵循以下规则:

  • 先执行类的load方法,再执行所有分类的load方法
  • 执行类的load方法时,是按照参与编译的顺序执行,先编译的类先执行。
  • 先执行父类的load方法,再执行自己的load方法
  • 执行分类的的load方法时,按照分类参与编译的顺序,先参与编译的分类先执行

1.3 执行方式

当分类中存在和本类中同名的方法时,调用这个方法最终执行的是分类中的方法。按理说调用load方法时最终只会调用其中一个分类的load方法,可是本类和分类都调用了load方法

因为load方法和普通方法调用方式不同,普通方法调用时通过消息发送机制实现的,会先去类或元类的方法列表中查找,如果找到了方法就执行,如果没有找到就去父类的方法列表中查找,只要找到就会终止查找,所以只会执行一次。

load方法调用时,每个类都是load方法的地址直接调用,而不会走objc_msgSend函数的方法查找流程,也就是说一个类有时限load方法就执行,没有就不执行(没有的话也不会去父类里面查找)

1.4 实现load方法时的注意点

我们通常在load方法中进行方法交换(Method Swizzle),除此之外,除非真的有必要,我们尽量不要在load方法中写代码,尤其不要在load方法中使用其它的类,因为这个时候其它的类可能还没有被加载进内存,随意使用可能会出问题。
如果确实要在load方法写一些代码,那也要尽量精简代码,不要做一些耗时或者等待锁的操作,因为整个程序在执行load方法时都会阻塞,从而导致程序启动时间过长甚至无法启动。

2. initialize 方法

2.1 调用时机

initialize 方法是在类或者子类收到第一条消息时被调用,这里的消息就是指实例方法或者类方法的调用,所以所有类的initialize调用是在main函数后调用的。而且一个类只会调用一次initialize 方法。如果一个类在城西运行过程中一直没有被使用过,那这个类的initialize方法也就不会被调用

2.2 调用方式

initialize方法的调用和普通方法调用一样,也是走的objc_msgSend流程。所以如果一个类和他的分类都实现了initialize方法,那么最终调用的是分类中的方法

如果子类和父类都实现了initialize方法,那么会先调用父类的方法,然后调用子类的方法。
子类中不需要写[super initialize]来调用父类的方法,通过查看源码得知它是在底层实现过程中主动调用的父类的initialize方法

2.3 实现initialize方法时的注意点

虽然使用initialize要比使用load安全(因为在调用initialize时所有类已经被加载进内存了),但我们还是要尽量少用initialize这个方法个,尤其要谨慎在分类中实现initialize方法,因为如果在分类中实现了,本类实现的initialize方法将不会被调用。实际开发中initialize方法一般用于初始化全局变量或静态变量。

3 总结

  • 调用时机和调用顺序不同:

load方法是在类被加载进内存时调用的,在main函数调用前被调用,且父类,子类,分类都会被调用,父类>子类>分类,同一级别的按编译顺序调用

initialize方法是在第一次方法调用时被调用,在main函数后

  • 执行方式不同:

load方法调用时,每个类都是根据load方法的地址直接调用,不会走objc_msgSend流程,也就是说一个类有实现load方法就执行,没有就不执行,没有的话也不会再父类里面查找

initialize方法调用方式和objc_msgSend流程一致,initialize默认会调用[super initialize]

  • 使用模式不同:

load方法常用于方法交换 Method_Swizzle

initialize常用于初始化全局变量或静态变量

转载自:https://juejin.im/post/5e130ba05188253a5d560155

相关文章

  • OC中的load和initialize的区别

    OC中的load和initialize的区别 调用方式load是根据函数地址直接调用initialize是通过ob...

  • iOS学习回顾

    oc部分 1. load和initialize的区别(利用load方法,MJRefresh在app启动时 在UIT...

  • load、initialize详解及区别

    load、initialize方法的区别? load、initialize的调用顺序? load initialize

  • OC 中load和initialize的区别

    + (void)load;+(void)initialize; load:load方法在这个文件被程序装载时调用。...

  • OC中load 和initialize 的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • OC中load和initialize的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • OC 中 load 和 initialize 的区别

    load: +load是一个类方法,当程序载入时,在main函数执行之前,带有+load方法类(Class)或者种...

  • OC中load和initialize的区别

    OC文件在编译后,类相关的数据结构会保留在目标文件中,在运行时得到解析和使用。在应用程序运行起来的时候,类的信息会...

  • 运行时的应用

    1、load和initialize的区别 +load和+initialize是 Objective-C runti...

  • 技术点

    1、oc中 load 和initialize 方法的异同? 连接 load 方法: 对于每个类(class)及分类...

网友评论

      本文标题:OC中load 和initialize 的区别

      本文链接:https://www.haomeiwen.com/subject/tmejuktx.html