重新认识 load 方法

Tags
iOS
Date
Mar 22, 2021
 

load

 
The load message is sent to classes and categories that are both dynamically loaded and statically linked, but only if the newly loaded class or category implements a method that can respond.
The order of initialization is as follows:
  1. All initializers in any framework you link to.
  1. All +load methods in your image.
  1. All C++ static initializers and C/C++ __attribute__(constructor) functions in your image.
  1. All initializers in frameworks that link to you.
 
直接通过函数地址调用,而不是objc_msgSend,所以分类和主类的load、子类和父类的load互不影响。

load_method_t load_method = (load_method_t)classes[i].method;
(*load_method)(cls, @selector(load));
load_method_t load_method = (load_method_t)cats[i].method;
cls = _category_getClass(cat);
(*load_method)(cls, @selector(load));
先执行主类的load,再执行分类的load
do {
    // 1. Repeatedly call class +loads until there aren't any more
    while (loadable_classes_used > 0) {
        call_class_loads();
    }

    // 2. Call category +loads ONCE
    more_categories = call_category_loads();

    // 3. Run more +loads if there are classes OR more untried categories
} while (loadable_classes_used > 0  ||  more_categories);
先执行父类的load,再执行子类的load
// Ensure superclass-first ordering
schedule_class_load(cls->getSuperclass());
按照编译顺序,先编译先执行(父类的分类的加载与子类的分类的加载的先后也取决于编译顺序)
classref_t const *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
load的执行时机。动态库或可执行文件加载时执行。
/***********************************************************************
* load_images
* Process +load in the given images which are being mapped in by dyld.
**********************************************************************/
void
load_images(const char *path __unused, const struct mach_header *mh)
通过类结构里的标志位,保证每个类的load只加入列表一次。如果没有这个标志位判断,那么沿着superclass调用时应该会导致重复加入列表。分类没有这个标志位,是因为分类不需要superclass-first
// class +load has been called
#define RW_LOADED             (1<<23)

static void schedule_class_load(Class cls)
{
    if (!cls) return;
    ASSERT(cls->isRealized());  // _read_images should realize

    if (cls->data()->flags & RW_LOADED) return;

    // Ensure superclass-first ordering
    schedule_class_load(cls->getSuperclass());

    add_class_to_loadable_list(cls);
    cls->setInfo(RW_LOADED); 
}
类和分类的load方法的从准备到执行,而且只执行一次,是通过动态数组来维护的。
// List of classes that need +load called (pending superclass +load)
// This list always has superclasses first because of the way it is constructed
static struct loadable_class *loadable_classes = nil;
static int loadable_classes_used = 0;
static int loadable_classes_allocated = 0;

// List of categories that need +load called (pending parent class +load)
static struct loadable_category *loadable_categories = nil;
static int loadable_categories_used = 0;
static int loadable_categories_allocated = 0;
 

Loading Comments...