iOS load方法

流程分析

收到回调

    _dyld_objc_notify_register(&map_images, load_images, unmap_image);

用到的数据结构:


struct loadable_class {
    Class cls;  // may be nil
    IMP method;
};


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

  • 当自定义类,没有实现load方法,而只有它的分类实现,那么不会加入到_objc_catlist数据段中
  • 当自定义类和分类都实现了load方法,分类会加入到_objc_catlist数据段中

read_image会将nlclslist里的类进行realizeClassWithoutSwift。这样如果一个自定义类,实现了load方法,在镜像映射完成的时候,也就被填充了内部信息。(只是类,不是分类这一步)
load_image会首先加载共享缓存中的分类
然后,准备那些实现了load方法的类prepare_load_methods

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

    runtimeLock.assertLocked();

    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);
        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");
        }
        printf("------------%s\n", cat->name);
        realizeClassWithoutSwift(cls, nil);
        ASSERT(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
}
    

这里有一个关键的方法是schedule_class_load,它会先将父类的class的load方法加入loadable_classes

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

schedule_class_load方法将有load方法的类加入loadable_classes

 category_t * const *categorylist = _getObjc2NonlazyCategoryList(mhdr, &count);

这个方法获取__objc_catlist2数据段下的分类,通过add_category_to_loadable_list(cat);方法加入loadable_categories

然后接下来通过call_load_methods()方法调用+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;
}

循环调用load方法,并调用分类的load方法

realizeClassWithoutSwift学习

realizeClassWithoutSwift这方法很重要,有空看

/***********************************************************************
* realizeClassWithoutSwift
* Performs first-time initialization on class cls, 
* including allocating its read-write data.
* Does not perform any Swift-side initialization.
* Returns the real class structure for the class. 
* Locking: runtimeLock must be write-locked by the caller
**********************************************************************/

你可能感兴趣的:(iOS load方法)