Objective-C——initialize方法调用原理分析

2 篇文章 0 订阅

一、调用时机

在类第一次接收到消息的时候调用

二、调用顺序

  • 先调用父类的initialize方法,再调用子类的initialize方法(递归,每个类只会初始化一次)
  • 如果子类没有实现initialize方法,则会调用父类的initialize方法(消息调用机制,通过superclass指针向上查找)(所以,父类的initialize方法可能会被调用多次)
  • 如果分类实现了initialize方法,会“覆盖”类本身的initialize调用(方法合并的时候,分类的方法更靠前)

三、源码窥探

// objc-initialize.mm
/***********************************************************************
* class_initialize.  Send the '+initialize' message on demand to any
* uninitialized class. Force initialization of superclasses first.
**********************************************************************/
void initializeNonMetaClass(Class cls) {
    ASSERT(!cls->isMetaClass());
    Class supercls;
    bool reallyInitialize = NO;
    // Make sure super is done initializing BEFORE beginning to initialize cls.
    // See note about deadlock above.
    supercls = cls->superclass;
    // 如果有父类,并且父类没有完成初始化
    if (supercls  &&  !supercls->isInitialized()) {
        // 递归初始化父类
        initializeNonMetaClass(supercls);
    }
    // 如果类没有完成初始化,并且不是正在初始化,标记成准备初始化
    if (!cls->isInitialized() && !cls->isInitializing()) {
        cls->setInitializing();
        reallyInitialize = YES;
    }
    if (reallyInitialize) {
        // 发送initialize消息:
        // ((void(*)(Class, SEL))objc_msgSend)(cls, @selector(initialize));
        callInitialize(cls);
        // Done initializing.
        /*
         // lockAndFinishInitializing 主要做了两件事:
         // 标记完成初始化
         cls->setInitialized();
         // 释放锁
         classInitLock.notifyAll();
         */
        lockAndFinishInitializing(cls, supercls);	
    }
}

四、示例分析(一)

1. 结构图(均实现了initialize方法)

在这里插入图片描述

2. 代码

①:[Person class];
②:[Student class];
③:[GoodStudent class];
④:[NorStudent class];
/// 调用结果
+[Person initialize]
+[Student initialize]
+[GoodStudent initialize]
+[NorStudent initialize]

3. 分析

  • 执行代码①,给Person发消息,Person的父类NBObjcet没有实现initialize方法,所以调用父类的方法,不会有打印信息,接着调用Person类中的initialize方法,打印+[Person initialize]
  • 执行代码②,给Student发消息,先看父类Person是否初始化,因为父类已经初始化,所以调用Student类的initialize方法,打印+[Student initialize]
  • 执行代码③,给GoodStudent发消息,先看父类Student是否初始化,代码执行逻辑同上
  • 执行代码④,给NorStudent发消息,代码执行逻辑同上

4. 总结

  1. 先调用父类的initialize方法,再调用子类的initialize方法
  2. 每个类只会初始化一次

五、实例分析(二)

1. 结构图(部分实现了initialize方法)

在这里插入图片描述

2. 代码

①:[Person class];
②:[Student class];
③:[GoodStudent class];
④:[NorStudent class];
/// 调用结果
+[Person initialize]
+[Student initialize]
+[Student initialize]
+[NorStudent initialize]

3. 分析

  • 代码①、②的执行逻辑同上

  • 执行代码③的逻辑如下图:
    在这里插入图片描述

    所以,Student的initialize方法会执行两次。

4. 总结

  1. 如果子类没有实现initialize方法,则会调用父类的initialize方法
  2. 父类的initialize方法可能会被调用多次
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值