18期_iOS_分类的加载分析

2023-08-20  本文已影响0人  萧修

在类的加载中,其中函数map_iamges为主要流程,最后执行read_images,此流程最后为分类的加载,看代码

void _read_images(header_info **hList, uint32_t hCount, int totalClasses, int unoptimizedTotalClasses)
{
    bool hasClassProperties = hi->info()->hasCategoryClassProperties();
    
    size_t count;
    auto processCatlist = [&](category_t * const *catlist) {
        for (unsigned i = 0; i < count; i++) {
            category_t *cat = catlist[i];
            Class cls = remapClass(cat->cls);
            locstamped_category_t lc{cat, hi};
            
        }
    }
}

由上面的代码可知,从macho中的objc_catlist读取的分类,我们来看category_t的结构。详细结构可查看分类的本质

懒加载和非懒加载

从以往经验中,实现+load方法的类,会提前加载。,此方法何时执行,接下来分析libobjc从dyld接受的`load_imags开始分析

_dyld_objc_notify_register(&map_images, load_images, unmap_image);
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);
        //准备load方法
        prepare_load_methods((const headerType *)mh);
    }

    // Call +load methods (without runtimeLock - re-entrant)
    //调用load方法
    call_load_methods();
}

//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");
        }
        realizeClassWithoutSwift(cls, nil);
        ASSERT(cls->ISA()->isRealized());
        add_category_to_loadable_list(cat);
    }
}

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

由上面三段代码:先父类后子类的,将+load方法添加到对应的loadable表中。

是否是懒加载,取决于由+load

类的懒加载和非懒加载与分类的懒加载和非懒加载,同友四种情况

类拓展和分类

类扩展是类编译时就被当做类的一部分,而分类是运行时才添加进去,而编译后的ro已经确定,属性要加入ro不被允许,rw没有成员变量字段,系统只声明set和getter

initialize

子类没有实现,父类实现,初始化子类父类会多次调用。

系统较早执行的方法

上一篇 下一篇

猜你喜欢

热点阅读