load

load方法什么时候调用?

method Swizzling 为什么要放在load方法里面?

 

/***********************************************************************

* _objc_init

* Bootstrap initialization. Registers our image notifier with dyld.

* Called by libSystem BEFORE library initialization time

**********************************************************************/

 

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

}

 

进入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 准备load方法

call_load_methods(); 所以load的方法是在所有loadImages之后,map映射到内存中之后调用的,在start函数之前

其中prepare_load_methods方法:

类的方法,分类,父类的load方法调用顺序?

load如何加载?

load如何调用? 

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

        realizeClass(cls);

        assert(cls->ISA()->isRealized());

        add_category_to_loadable_list(cat);

    }

}

 

 

/***********************************************************************

* call_load_methods

* Call all pending class and category +load methods.

* Class +load methods are called superclass-first. 

* Category +load methods are not called until after the parent class's +load.

* 

* This method must be RE-ENTRANT, because a +load could trigger 

* more image mapping. In addition, the superclass-first ordering 

* must be preserved in the face of re-entrant calls. Therefore, 

* only the OUTERMOST call of this function will do anything, and 

* that call will handle all loadable classes, even those generated 

* while it was running.

*

* The sequence below preserves +load ordering in the face of 

* image loading during a +load, and make sure that no 

* +load method is forgotten because it was added during 

* a +load call.

* Sequence:

* 1. Repeatedly call class +loads until there aren't any more

* 2. Call category +loads ONCE.

* 3. Run more +loads if:

*    (a) there are more classes to load, OR

*    (b) there are some potential category +loads that have 

*        still never been attempted.

* Category +loads are only run once to ensure "parent class first" 

* ordering, even if a category +load triggers a new loadable class 

* and a new loadable category attached to that class. 

*

* Locking: loadMethodLock must be held by the caller 

  All other locks must not be held.

**********************************************************************/

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_class_loads

* Call all pending class +load methods.

* If new classes become loadable, +load is NOT called for them.

*

* Called only by call_load_methods().

**********************************************************************/

static void call_class_loads(void)

{

    int i;

    

    // Detach current loadable list.

    struct loadable_class *classes = loadable_classes;

    int used = loadable_classes_used;

    loadable_classes = nil;

    loadable_classes_allocated = 0;

    loadable_classes_used = 0;

    

    // Call all +loads for the detached list.

    for (i = 0; i < used; i++) {

        Class cls = classes[i].cls;

        load_method_t load_method = (load_method_t)classes[i].method;

        if (!cls) continue; 

 

        if (PrintLoading) {

            _objc_inform("LOAD: +[%s load]\n", cls->nameForLogging());

        }

        (*load_method)(cls, SEL_load);

    }

    

    // Destroy the detached list.

    if (classes) free(classes);

}

 

 

猜你喜欢

转载自www.cnblogs.com/coolcold/p/12056909.html