Category-加载流程、底层结构分析

954 阅读2分钟

Category加载流程

当我们启动App时,会对Objc类进行初始化,这里我们探讨的是关于Category的加载流程,如上图所示.

在load_categories_nolock方法中通过_getObjc2CategoryList获取分类列表,在attachCategories()方法中,首先会初始化三个数组,分别是method_list_tproperty_list_t,protocol_list_t,并申明数组的容量大小ATTACH_BUFSIZ = 64, 在官方注释中,解释到只有少数的几个类拥有超过64个类别

  * Only a few classes have more than 64 categories during launch.
  * This uses a little stack, and avoids malloc.

然后遍历分类列表,将分类的信息附加到对应class中,按照编译顺序,最后编译的方法将会放在前面,同时将方法添加到类后,更新方法缓存列表。

Category底层结构分析

如上图,Category是个category_t结构体,其内包含了类名、关联类、实例方法列表、类方法列表、协议列表、实例属性列表、类属性列表。

Category添加属性

通过category_t可知,我们可以通过分类添加方法、属性以及协议,那么如何通过分类添加属性呢?property = _ivar + setter + getter,通常我们在类中声明一个属性时,编译器会默认的帮我们实现setter、getter方法,那么我们在分类中声明一个属性时,编译器会帮我们默认实现嘛?

分类添加属性,未实现setter、getter方法,通过lldb调试打印此时person类中class_rw_t内的信息,可以看到声明的nickName属性,但是methods列表内只有init方法,编译时编译器已经给出警告,Property 'nickName' requires method 'nickName' to be defined - use @dynamic or provide a method implementation in this category,

可以看出,当我们在分类中添加属性时,得自己实现对应的setter、getter方法,通过关联对象objc_setAssociatedObject实现属性的存储。