1、+ initialize方法会在类第一次接受到消息时调用

2、+initialize方法是通过objc_msgSend函数(消息发送机制)调用

2.1、如果子类没有实现+initialize,会调用父类的+initialize(所以父类的+initialize可能会被调用多次)
2.2、如果分类实现了+initialize,会覆盖类本身的+initialize的调用

调用顺序

1、先调用父类的+initialize方法,再调用子类的+initialize方法(如果有实现+initialize时) — 先初始化父类,再初始化子类,每个类只会初始化一次

2、遵循消息发送机制的方法查找顺序

============================== 源码解读顺序 ==============================
/*1、lookUpImpOrForward2、initializeAndLeaveLocked3、initializeAndMaybeRelock4、initializeNonMetaClass5、callInitialize6、objc_msgSend
*/
============================== 核心代码查看 ==============================
//  内部也是调用 class_getInstanceMethod方法
Method class_getClassMethod(Class cls, SEL sel)
{if (!cls  ||  !sel) return nil;return class_getInstanceMethod(cls->getMeta(), sel);
}/*class_getInstanceMethod方法的实现接下来查看 lookUpImpOrForward方法的实现
*/
Method class_getInstanceMethod(Class cls, SEL sel)
{if (!cls  ||  !sel) return nil;
#warning fixme build and search caches// Search method lists, try method resolver, etc.lookUpImpOrForward(nil, sel, cls, LOOKUP_RESOLVER);
#warning fixme build and search cachesreturn _class_getMethod(cls, sel);
}/*if (slowpath((behavior & LOOKUP_INITIALIZE) && !cls->isInitialized())) {标识需要初始化,并且这个类是还没有被初始化的接下来查看 cls = initializeAndLeaveLocked(cls, inst, runtimeLock);
*/
MP lookUpImpOrForward(Class cls, SEL sel, id inst, bool initialize, bool cache, bool resolver)
{const IMP forward_imp = (IMP)_objc_msgForward_impcache;IMP imp = nil;Class curClass;runtimeLock.assertUnlocked();// Optimistic cache lookupif (fastpath(behavior & LOOKUP_CACHE)) {imp = cache_getImp(cls, sel);if (imp) goto done_nolock;}runtimeLock.lock();checkIsKnownClass(cls);if (slowpath(!cls->isRealized())) {cls = realizeClassMaybeSwiftAndLeaveLocked(cls, runtimeLock);}if (slowpath((behavior & LOOKUP_INITIALIZE) && !cls->isInitialized())) {cls = initializeAndLeaveLocked(cls, inst, runtimeLock);}/*省略其他代码*/return imp;
}static Class initializeAndLeaveLocked(Class cls, id obj, mutex_t& lock)
{return initializeAndMaybeRelock(cls, obj, lock, true);
}// 查看initializeNonMetaClass(nonmeta)方法
static Class initializeAndMaybeRelock(Class cls, id inst,mutex_t& lock, bool leaveLocked)
{lock.assertLocked();ASSERT(cls->isRealized());if (cls->isInitialized()) {if (!leaveLocked) lock.unlock();return cls;}Class nonmeta = getMaybeUnrealizedNonMetaClass(cls, inst);if (nonmeta->isRealized()) {lock.unlock();} else {nonmeta = realizeClassMaybeSwiftAndUnlock(nonmeta, lock);cls = object_getClass(nonmeta);}ASSERT(nonmeta->isRealized());initializeNonMetaClass(nonmeta);if (leaveLocked) runtimeLock.lock();return cls;
}/*if (supercls  &&  !supercls->isInitialized())表示父类存在,且没有进行过初始化initializeNonMetaClass(supercls);递归调用,此处可以说明会先调用父类的initialize方法接下来查看 callInitialize(cls);
*/
void initializeNonMetaClass(Class cls)
{ASSERT(!cls->isMetaClass());Class supercls;bool reallyInitialize = NO;supercls = cls->superclass;if (supercls  &&  !supercls->isInitialized()) {initializeNonMetaClass(supercls);}SmallVector<_objc_willInitializeClassCallback, 1> localWillInitializeFuncs;{monitor_locker_t lock(classInitLock);if (!cls->isInitialized() && !cls->isInitializing()) {cls->setInitializing();reallyInitialize = YES;localWillInitializeFuncs.initFrom(willInitializeFuncs);}}if (reallyInitialize) {_setThisThreadIsInitializingClass(cls);if (MultithreadedForkChild) {performForkChildInitialize(cls, supercls);return;}for (auto callback : localWillInitializeFuncs)callback.f(callback.context, cls);if (PrintInitializing) {_objc_inform("INITIALIZE: thread %p: calling +[%s initialize]",objc_thread_self(), cls->nameForLogging());}
#if __OBJC2__@try
#endif{callInitialize(cls);if (PrintInitializing) {_objc_inform("INITIALIZE: thread %p: finished +[%s initialize]",objc_thread_self(), cls->nameForLogging());}}
#if __OBJC2__@catch (...) {if (PrintInitializing) {_objc_inform("INITIALIZE: thread %p: +[%s initialize] ""threw an exception",objc_thread_self(), cls->nameForLogging());}@throw;}@finally
#endif{lockAndFinishInitializing(cls, supercls);}return;}else if (cls->isInitializing()) {if (_thisThreadIsInitializingClass(cls)) {return;} else if (!MultithreadedForkChild) {waitForInitializeToComplete(cls);return;} else {_setThisThreadIsInitializingClass(cls);performForkChildInitialize(cls, supercls);}}else if (cls->isInitialized()) {return;}else {_objc_fatal("thread-safe class init in objc runtime is buggy!");}
}// objc_msgSend方式调用SEL_initialize
void callInitialize(Class cls)
{((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);asm("");
}
PS 此文为学习 李明杰 老师的 iOS底层原理课程所写笔记

initialize方法相关推荐

  1. iOS load方法和initialize方法的异同

    对于OC中的类来说,在runtime中会有两个方法被调用: +load +initialize 这两个方法看起来都是在类初始的时候调用的,但其实还是有一些异同,从而可以用来做一些行为. +load 首 ...

  2. initialize方法与load方法比较

    load方法和initialize方法类似点 1. 都只会调用一次2. 父类在子类之前加载 复制代码 不同点在于: 1. 加载时间不同,load方法在main()函数前进行调用,initialize在 ...

  3. OC 中 load 方法和 initialize 方法的异同

    + (void)load; 当类对象被引入项目时, runtime 会向每一个类对象发送 load 消息 load 方法会在每一个类甚至分类被引入时仅调用一次,调用的顺序:父类优先于子类, 子类优先于 ...

  4. 重写美味不用等(1) 单例 --initialize方法调用

    initialize实在一个类第一次发消息前调用,就是说,第一次调用init, 私用方法, 类方法调用之前会调用它,也只调用一次. .h文件 + (instancetype)sharedInstanc ...

  5. SAP S/4HANA生产订单的BAdI增强点之Initialize方法

    在S/4HANA里创建生产订单时,有一个增强点WORKORDER_UPDATE: 这个CAUFVDB里存放的是生产订单抬头级别的数据: 我们来观察下运行时这个结构里存放的数据. 请大家用我github ...

  6. oc---类方法load和initialize的区别

    在iOS开发中,就像Application有生命周期回调方法一样,在Objective-C的类被加载和初始化的时候,也可以收到方法回调,可以在适当的情况下做一些定制处理.而这正是本篇文章所要介绍的lo ...

  7. +load +initialize

    +load方法 在app启动的时候各个类的+load方法都会被调用,+load方法不是通过消息机制调用的,它是直接调用的,因此无论是在子类或者category中复写此方法,复写的+load方法都会被调 ...

  8. iOS 中 load 和 initialize的实现顺序

    1 load 函数 调用时机,当类引用进项目的时候执行load函数,在main函数开始之前,与 这个类是否被用到是无关的,每个类的load函数都会自动调用一次. 1 父类和子类都实现load函数的时候 ...

  9. 你需要了解的load和initialize

    NSObject类有两种初始化方式load和initialize load + (void)load; 复制代码 对于加入运行期系统的类及分类,必定会调用此方法,且仅调用一次. iOS会在应用程序启动 ...

最新文章

  1. CommonJS规范与AMD规范的理解
  2. html css 水平时间轴,纯css+js水平时间轴
  3. Hbase的WebUI中的RegionServers不显示集群机器域名
  4. matlab 随机森林算法_随机森林算法
  5. BZOJ1016:[JSOI2008]最小生成树计数——题解
  6. 金蝶Apusic应用服务器的数据源管理(转)
  7. Web框架——Flask系列之WTF表单验证练习(七)
  8. Python 没有函数重载?如何用装饰器实现函数重载?
  9. SpringBoot中使用Mybatis-plus整合PageHelper分页插件踩坑
  10. Mac中将Apple移动设备(iPhone或iPad)屏幕录屏转换为gif图片的极简方法
  11. C# IntPtr类型转换
  12. Bing Maps-----微软
  13. 什么是IaaS PaaS SaaS,看这一篇就够了
  14. Android MTU 值修改
  15. C++蜜蜂的爬行路线
  16. java中的Dao类,model类是什么意思
  17. Linux下制作bin文件,并对其进行截取、合并、修改
  18. Bigemap中批量添加第三方在线地图教程
  19. vue打包出来的dist如何查看js的占比,report生成分析图
  20. 年度总结 | 积跬步以至千里,2023一起筑梦新征程

热门文章

  1. laravel邮箱找回密码
  2. error: RC2135 : file not found:
  3. 计算机常用涵数有哪些,计算机常用函数.doc
  4. 计算机操作系统感悟随笔--实例思考
  5. 台式计算机包装清单,台式电脑主机箱的运输包装设计.docx
  6. Spring MVC:HTTP消息转换器
  7. python二维分布图怎么画_Python可视化二维高斯分布
  8. 关于windows10休眠文件的开启和关闭
  9. PC_规格化数及尾数相关表示形式和范围
  10. matlab非线性约束条件,MATLAB 非线性规划及非线性约束条件求解