Call rules for load

  1. The load method of a class is called after all the load method calls of its parent class
  2. The load method of the class is called after the load method of the current class is called
  3. The order in which the load methods of a class are called depends on the order in which they are compiled

explore

Just as in the previous article you explored the underlying principles of categories by hand, open the objc source code directly and proceed to the _objc_init function

void _objc_init(void)
{
    static bool initialized = false;
    if (initialized) return;
    initialized = true;
    
    // fixme defer initialization until an objc-using image is found?
    environ_init();
    tls_init();
    static_init();
    lock_init();
    exception_init();

    _dyld_objc_notify_register(&map_images, load_images, unmap_image);
}
Copy the code
  • The previously mentionedload_imagesIt is dyLD that initializes the loading image method, so it should be explored this time
void
load_images(const char *path __unused, const struct mach_header *mh)
{
    // Return without taking locks if there are no +load methods here.
    if(! hasLoadMethods((const headerType *)mh)) return;

    recursive_mutex_locker_t lock(loadMethodLock);

    // Discover load methods
    {
        mutex_locker_t lock2(runtimeLock);
        / * * * /
        prepare_load_methods((const headerType *)mh);
    }

    // Call +load methods (without runtimeLock - re-entrant)
    call_load_methods();
}
Copy the code
  • We found what we were looking forloadMethod, first to exploreprepare_load_methodsWhat did you do? I’ll see it latercall_load_methods
void prepare_load_methods(const headerType *mhdr)
{
    size_t count, i;

    runtimeLock.assertLocked();

    Load the list of classes from the Macho file
    classref_t *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
    for (i = 0; i < count; i++) {
        // Array: [< CLS,method>,< CLS,method>,< CLS,method>
        schedule_class_load(remapClass(classlist[i]));
    }

    // For the classification of operations!
    category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
    for (i = 0; i < count; i++) {
        category_t *cat = categorylist[i];
        Class cls = remapClass(cat->cls);
        if(! cls)continue;  // category for ignored weak-linked classrealizeClass(cls); assert(cls->ISA()->isRealized()); add_category_to_loadable_list(cat); }}Copy the code
  • getObjc2NonlazyClassListfromMach-OThe file retrieves a list of classes that are not lazily loaded, then loops through the list of classes, calling a recursive methodschedule_class_load
  • Take a look atschedule_class_loadWhat did
  • schedule_class_loadCall the parent class recursively, all the way up to the parent class and call it, so this demonstrates our first conclusion at the beginning of this article:The load method of a class is called after all the load method calls of its parent class
  • So let’s seeadd_class_to_loadable_list
  • Back outside
 // For the classification of operations!
    category_t **categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
    for (i = 0; i < count; i++) {
        category_t *cat = categorylist[i];
        Class cls = remapClass(cat->cls);
        if(! cls)continue;  // category for ignored weak-linked class
        realizeClass(cls);
        assert(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
Copy the code
  • It can be seen that the classification is also a non-lazy load classification obtained from the Mach-O file. It is verified that the call order of the load method of the classification is related to the compile order, and the load method is called in different order

  • Add_category_to_loadable_list what does this method do

  • This is similar to add_class_to_loadable_list above, except that it is loaded into the global container of the classification

  • Now that we’re done exploring prepare_load_methods, let’s go back and see what call_load_methods does

  • The load method of the class is called after the load method of the current class

  • Call_class_loads is called by SEL of load

  • Call_category_loads similarly

conclusion