美文网首页
load方法探索

load方法探索

作者: Code_人生 | 来源:发表于2019-09-29 16:14 被阅读0次

一、调用规则

  • 1、一个类的load方法在所有父类load方法调用之后调用
  • 2、分类的load方法在当前类的load方法调用之后调用
  • 3、分类load的调用顺序和编译顺序有关(这个就不需要考虑分类对应的类的父子关系了)

总结:
1、先调用所有类的load方法,调用顺序和编译顺序有关,如果有父类先调用父类的,再调用自己(这时如果父类的编译顺序再后面,也会先调用父类的,再调用自己的)(如果父类在前面那就直接调用了哈)
2、再调用分类的load方法,调用顺序和编译顺序有关(这个就不需要考虑分类对应的类的父子关系了)

二、load方法的调用

  • objc4-750源码中搜索_objc_init
  • _dyld_objc_notify_register(&map_images, load_images, unmap_image);
    • &map_images dyld将image加载进内存
    • load_images dyld初始化image,load方法也在此调用
    • unmap_image 移除内存
// objc-os.mm
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);
}
  • 步骤1、点击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();
}
  • 步骤2、点击prepare_load_methods
void prepare_load_methods(const headerType *mhdr)
{
    size_t count, i;

    runtimeLock.assertLocked();

    //从 Macho 文件加载类的列表
    classref_t *classlist = 
        _getObjc2NonlazyClassList(mhdr, &count);
    for (i = 0; i < count; i++) {
        //数组:[<cls,method>,<cls,method>,<cls,method>] 有顺序
        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);
    }
}
  • 步骤2.1、点击schedule_class_load
//递归调用
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->superclass);
    add_class_to_loadable_list(cls);
    cls->setInfo(RW_LOADED); 
}
  • 点击add_class_to_loadable_list
void add_class_to_loadable_list(Class cls)
{
    IMP method;

    loadMethodLock.assertLocked();

    method = cls->getLoadMethod();
    if (!method) return;  // Don't bother if cls has no +load method
    
    if (PrintLoading) {
        _objc_inform("LOAD: class '%s' scheduled for +load", 
                     cls->nameForLogging());
    }
    
    if (loadable_classes_used == loadable_classes_allocated) {
        loadable_classes_allocated = loadable_classes_allocated*2 + 16;
        loadable_classes = (struct loadable_class *)
            realloc(loadable_classes,
                              loadable_classes_allocated *
                              sizeof(struct loadable_class));
    }
    
    loadable_classes[loadable_classes_used].cls = cls;
    loadable_classes[loadable_classes_used].method = method;
    loadable_classes_used++;
}
  • 步骤2.2、点击add_category_to_loadable_list
void add_category_to_loadable_list(Category cat)
{
    IMP method;

    loadMethodLock.assertLocked();

    method = _category_getLoadMethod(cat);

    // Don't bother if cat has no +load method
    if (!method) return;

    if (PrintLoading) {
        _objc_inform("LOAD: category '%s(%s)' scheduled for +load", 
                     _category_getClassName(cat), _category_getName(cat));
    }
    
    if (loadable_categories_used == loadable_categories_allocated) {
        loadable_categories_allocated = loadable_categories_allocated*2 + 16;
        loadable_categories = (struct loadable_category *)
            realloc(loadable_categories,
                              loadable_categories_allocated *
                              sizeof(struct loadable_category));
    }

    loadable_categories[loadable_categories_used].cat = cat;
    loadable_categories[loadable_categories_used].method = method;
    loadable_categories_used++;
}
  • 步骤3、点击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) {
            //先调用类的 load 方法
            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;
}
  • 总结
    • 1、load_images
    • 2、prepare_load_methods
      • 2.1、调整当前的调用顺序
      • 2.2、类,递归遍历,loadable_classes<cls,method>
      • 2.3、分类,loadable_category,编译顺序有关的!
    • 3、call_load_methods()
      • 3.1、先调用loadable_classes
      • 3.2、后调用loadable_category

相关文章

  • load方法探索

    一、调用规则 1、一个类的load方法在所有父类load方法调用之后调用 2、分类的load方法在当前类的load...

  • iOS - load 方法探索

    [toc] 参考 load initialize http://www.jianshu.com/p/a358a39...

  • iOS程序加载流程—dyld流程

    本篇文章主要是探索程序启动流程。 load方法断点 首先我们来个简单程序 通过打印我们知道+load > c++构...

  • 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...

  • 常见面试题--Category、load 、initialize

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

  • +load、+initialize 以及分类的加载

    +load: 1.+load方法什么时候调用? 2.+load方法调用原理 3.+load方法调用顺序? 4.举例...

网友评论

      本文标题:load方法探索

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