基础

问题:+(void)load; +(void)initializ

2020-08-21  本文已影响0人  姜小舟

两个方法都可以进行一些类的初始化操作。其中有些小区别。

+(void)load 方法

+(void)initialize 方法

runtime 源码如下:

IMP lookUpImpOrForward(Class cls, SEL sel, id inst,
                     bool initialize, bool cache, bool resolver) {
  ...
      rwlock_unlock_write(&runtimeLock);
  }

  if (initialize  &&  !cls->isInitialized()) {
      _class_initialize (_class_getNonMetaClass(cls, inst));
      // If sel == initialize, _class_initialize will send +initialize and 
      // then the messenger will send +initialize again after this 
      // procedure finishes. Of course, if this is not being called 
      // from the messenger then it won't happen. 2778172
  }

  // The lock is held to make method-lookup + cache-fill atomic 
  // with respect to method addition. Otherwise, a category could 
  ...
}

+initialize 方法最核心的源码

void _class_initialize(Class cls) {
  ...
  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()) {
      _class_initialize(supercls);
  }

  // Try to atomically set CLS_INITIALIZING.
  monitor_enter(&classInitLock);
  if (!cls->isInitialized() && !cls->isInitializing()) {
      cls->setInitializing();
      reallyInitialize = YES;
  }
  monitor_exit(&classInitLock);

  if (reallyInitialize) {
      // We successfully set the CLS_INITIALIZING bit. Initialize the class.

      // Record that we're initializing this class so we can message it.
      _setThisThreadIsInitializingClass(cls);

      // Send the +initialize message.
      // Note that +initialize is sent to the superclass (again) if 
      // this class doesn't implement +initialize. 2157218
      if (PrintInitializing) {
          _objc_inform("INITIALIZE: calling +[%s initialize]",
                       cls->nameForLogging());
      }

      ((void(*)(Class, SEL))objc_msgSend)(cls, SEL_initialize);

      if (PrintInitializing) {
          _objc_inform("INITIALIZE: finished +[%s initialize]",
  ...
}

+load 方法 和 +initialize 方法比较

+load +initialize
调用时机 被添加到 runtime 时 收到第一条消息前,可能永远不调用
调用顺序 父类->子类->分类 父类->子类
调用次数 1次 多次
是否需要显式调用父类实现
是否沿用父类的实现
分类中的实现 类和分类都执行 覆盖类中的方法,只执行分类的实现
上一篇 下一篇

猜你喜欢

热点阅读