美文网首页
18期_iOS_分类的加载分析

18期_iOS_分类的加载分析

作者: 萧修 | 来源:发表于2023-08-20 01:00 被阅读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【分类未实现load】
  • 分类是非懒加载的,根据类是否是懒加载决定加载流程。
    类为懒加载:会在分类的+load之前调用前加载。(因为分类的方法要附加到类中,realizeClassWithoutSwift - methodizeClass
    类为非懒加载:类启动的时候就加载了,在read_images附加分类信息
  • 类懒加载,根据分类是懒加载,分类懒加载,第一次使用加载,非懒加载,分类的+load之前被加载

类拓展和分类

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

initialize

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

系统较早执行的方法

相关文章

  • 类的加载(下)-- 分类的加载

    前言 前面已经分析完了类的加载流程以及引出了分类的加载,并且得出了分类加载的两条路线。那么这篇文章还是继续往下分析...

  • 类的加载(下)

    上篇文章我们了解了类的加载和分类的数据准备 这篇我们继续分析分类的加载时机以及是如何加载到类中的 当类加载时,进入...

  • 13、分类的加载分析

    在main中定义LGperson的分类LG 一、分类的本质 探索分类的本质,有以下三种方式:1、通过 clang2...

  • Objective-C 类的加载原理(下)

    根据上篇文章的分析,分类的加载有两条线路: methodizeClass -> attachToClass -> ...

  • iOS底层原理20:类扩展与关联对象底层原理探索

    在前面的文章中,我们分析了类和分类的本质和加载过程,本文主要来分析类扩展和关联对象 【面试题】类扩展与分类的区别 ...

  • SDWebImage - Category

    各种分类:以UIView+WebCache为例分析 UIButton+WebCache为UIButton类添加载图...

  • iOS Objective-C 分类的加载

    iOS Objective-C 分类的加载 前言 在我的另一篇文章iOS 应用的加载objc篇中分析了在objc中...

  • iOS底层探索 --- 类的加载(下)

    在前两篇文章中,我们分析了类的加载。但是在类的加载过程中,不仅仅是类本身的加载,还有分类,类的扩展等的加载。下面我...

  • iOS 类的扩展&关联对象

    前言 在之前的文章中,我们已经分析了分类的本质和加载原理,不熟悉的同学可以查阅iOS-类的加载(下)[https:...

  • 类与分类搭配加载分析

    OC类与分类搭配加载分析 dyld加载数据,数据到底是怎么读取出来的? 类信息非常重要的方法 1.readClas...

网友评论

      本文标题:18期_iOS_分类的加载分析

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