iOS load_images

load_images的作用?
objc的开源代码中注释是这么写的。

Process +load in the given images which are being mapped in by dyld。
意思就是处理由dyld映射的image中的+load方法。

源码探究

接下来我们来看看load_images的源码。

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

这段代码中主要包含两个部分,一个是prepare_load_methods,一个是call_load_methods

prepare_load_methods

void prepare_load_methods(const headerType *mhdr)
{
    size_t count, i;

    runtimeLock.assertLocked();

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

    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
        if (cls->isSwiftStable()) {
            _objc_fatal("Swift class extensions and categories on Swift "
                        "classes are not allowed to have +load methods");
        }
        realizeClassWithoutSwift(cls);
        assert(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
}

在这个阶段主要做了以下几件事情。

  • 获取所有的非懒加载类(也就是实现了+(void)load方法的类)。
  • 通过schedule_class_load递归处理本类的所有父类,最终调用add_class_to_loadable_listClass+load方法存进一个结构体数组中。
  • 获取所有非懒加载的分类。
  • 调用realizeClassWithoutSwift对主类进行处理。
  • 将分类中的Class+load方法添加进另一个管理分类+load方法的结构体数组中。

至此在调用之前的预处理工作就做完了。

call_load_methods

调用所有的+(void)load方法。

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;
}
  • 针对所有的类进行遍历调用。
  • call_category_loads对当前类的所有分类进行遍历调用。
  • 先本类后分类。
  • 父类的方法优先于分类。

你可能感兴趣的:(iOS load_images)