“This is the 19th day of my participation in the First Challenge 2022, for more details: First Challenge 2022”.

Take a look atattachListsHow this method combines a list into one.

void attachLists(List* const * addedLists, uint32_t addedCount) {
        if (addedCount = = 0) return;

        if (hasArray()) {
            // many lists -> many lists
            uint32_t oldCount = array()->count;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)realloc(array(), array_t::byteSize(newCount)));
            array()->count = newCount;
            memmove(array()->lists + addedCount, array()->lists, 
                    oldCount * sizeof(array()->lists[0]));
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0]));
        }
        else if (!list  &&  addedCount = = 1) {
            // 0 lists -> 1 list
            list = addedLists[0];
        } 
        else {
            // 1 list -> many lists
            List* oldList = list;
            uint32_t oldCount = oldList ? 1 : 0;
            uint32_t newCount = oldCount + addedCount;
            setArray((array_t *)malloc(array_t::byteSize(newCount)));
            array()->count = newCount;
            if (oldList) array()->lists[addedCount] = oldList;
            memcpy(array()->lists, addedLists, 
                   addedCount * sizeof(array()->lists[0])); }}Copy the code

Memmove moves the original list back to addedCount, while memcpy copies the new addedLists to the front of the original list. This shows that the method of the same name of the classification overwriting the main class is not really overwritten, but the method of the classification is ranked first, and when the method is searched, the method implementation of the classification is returned

Calls the method of the same name that is categorized as queue-jumping

Add the sayYes method to both the categorization and the main class, and type the following code into the categorization sayNo method

unsigned int methodCount = 0;
    Method *methodList = class_copyMethodList([self class].&methodCount);
    
    IMP lastIMP = nil;
    for (NSInteger i = 0; i < methodCount; ++i) {
        Method method = methodList[i];
        NSString *selName = NSStringFromSelector(method_getName(method));
        if ([@"sayYes" isEqualToString:selName]) {
            lastIMP = method_getImplementation(method);
            ((void(*)(void))lastIMP)(); }}Copy the code

You’ll notice that both the main class and the categorized sayYes are gone

By the way+loadOrder of methods

Before call_load_methods, prepare_load_methods is called to find the +load method, which handles non-lazy-loaded classes and non-lazy-loaded classes.

classref_t const *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
    for (i = 0; i < count; i++) {
        schedule_class_load(remapClass(classlist[i]));
    }


category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);
    for (i = 0; i < count; i++) {
        category_t *cat = categorylist[i];
        Class cls = remapClass(cat->cls);
        //printf("%s--%s\n",cls->nameForLogging(),cat->name);
        if (!cls) continue;  // category for ignored weak-linked class
        if (cls->isSwiftStable()) {
            _objc_fatal("Swift class extensions and categories on Swift "
                        "classes are not allowed to have +load methods");
        }
        realizeClassWithoutSwift(cls, nil);
        ASSERT(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
Copy the code

I’m going to go to schedule_class_load, which has a little code in it

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

    add_class_to_loadable_list(cls);
    cls->setInfo(RW_LOADED);
Copy the code

When adding a class’s +load method to the class’s load list, schedule_class_load first adds the parent class’s +load method to the class’s load list. This ensures that the parent class calls +load before the subclass, and then adds the class’s +load method to the class’s load list. The +load order of the classification depends on the order in which the file was compiled.

The real call+loadMethod iscall_load_methods
void call_load_methods(void)
{
    static bool loading = NO;
    bool more_categories;

    loadMethodLock.assertLocked();

    // Re-entrant calls do nothing; the outermost call will finish the job.
    if (loading) return;
    loading = YES;

    void *pool = objc_autoreleasePoolPush();

    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);

    objc_autoreleasePoolPop(pool);

    loading = NO;
}
Copy the code

As you can see from the code, the load method of the class is called first, and then the load method of the class is called.

verify

The +load of the class does not override the +load of the class. There is nothing special done here. The +load of the class does override the +load of the class. (*load_method)(CLS, @selector(load));) , so it will be called whenever it is implemented.

To summarize the following load call order: the parent class is called before the child class, the main class is called before the class, and the class depends on the file compile order

Here is the analysis, error please big guy correct.