美文网首页
十二、+ load方法分析

十二、+ load方法分析

作者: KB_MORE | 来源:发表于2020-09-24 18:11 被阅读0次

load方法加载顺序

图片.png

类: LGPerson
子类: LGTeacher
分类1: LGPerson+EatFirst.h 先创建
分类2:LGPerson+DrinkSecond 后创建

调用顺序

-> 子类 -> 分类(后创建) -> 分类(先创建)

注意: 这里分类的load调用顺序是和编译顺序有关的(Compile Sources在前面,先调用那个)和创建顺序无关, 不过我们一般不会刻意的去调整文件在Compile Sources的顺序

图片.png

探究

首先我们先在类中重写下load方法, 然后打个断点, 运行项目,可以看到堆栈的调用情况

堆栈调用.png
可以看到在 load调用之前调用了load_images, 我们在objc的源码中可以找到load_images的实现,
其实load_images是在_objc_init函数中调用的, 下面看下几个函数的实现

objc的源码可以查看源码调试准备

_objc_init

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();
    runtime_init();
    exception_init();
    cache_init();
    _imp_implementationWithBlock_init();

    _dyld_objc_notify_register(&map_images, load_images, unmap_image);

#if __OBJC2__
    didCallDyldNotifyRegister = true;
#endif
}

load_images

void
load_images(const char *path __unused, const struct mach_header *mh)
{
    if (!didInitialAttachCategories && didCallDyldNotifyRegister) {
        didInitialAttachCategories = true;
        loadAllCategories();
    }

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

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

call_load_methods中其实我们就可以看到类和分类的调用顺序了,类先于分类
再看call_class_loads的实现

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, @selector(load));
    }
    
    // Destroy the detached list.
    if (classes) free(classes);
}

断点调试,


图片.png

会看到classes里面包含了LGPersonLGTeacher, 如果再多创建子类, 这里也会有变化
到这里就可以得出结论,

调用父类的load方法, 然后是子类的load方法
并且load方法并不是使用的消息发送 objc_msgSend 而是直接指针调用

相关文章

  • 十二、+ load方法分析

    load方法加载顺序 类: LGPerson子类: LGTeacher分类1: LGPerson+EatFirst...

  • category原理探究-2

    +load 方法解析 分析load方法前先来做一个小测验: 我们来运行一下程序,发现没有调用这些类但是load方法...

  • OC 底层探索 - load 和 initialize

    目录1. load1.1 load 方法的调用1.2 场景分析1.3 源码分析2. initialize2.1 i...

  • Glide 源码分析之三 into

    前言 在前两篇中,我们分析完了 with() 和 load() 方法:Glide 分析之一 withGlide 分...

  • Category的底层分析之load

    今天我们就围绕一个面试题来从源码的角度分析答案! 一、Category中有load方法吗?load方法是什么时候调...

  • jQuery |AJAX load() 方法

    jQuery load() 方法 jQuery load() 方法是简单但强大的 AJAX 方法。 load() ...

  • Category-load方法

    01load方法的基本使用 Category中有load方法吗?load方法是什么时候调用的?load 方法能继承...

  • OC分类二(Category)

    +load M、题:Category中有load方法吗?load方法什么时候调用?load方法能继承吗? 答:有;...

  • load

    1、category中有load方法吗?load方法是什么时候调用的?方法能继承么?1)有load方法2)load...

  • Category 的原理

    疑问?Category中有load方法吗?load方法是什么时候调用的?load 方法能继承吗?load、init...

网友评论

      本文标题:十二、+ load方法分析

      本文链接:https://www.haomeiwen.com/subject/surtuktx.html