IOS Category和Extension实现原理详解,使用场

2020-01-14  本文已影响0人  有梦想的狼

category:

category是Objective-C 2.0之后添加的语言特性,别人口中的分类、类别其实都是指的category。category的主要作用是为已经存在的类添加方法。
category编译之后的底层结构是struct category_t,里面存储着分类的对象方法、类方法、属性、协议信息,在程序运行的时候,runtime会将category的数据合并到类信息中(类对象、元类对象中)。

category使用场合:

category特点:

category调用优先级:

分类(category) > 本类 > 父类。即,优先调用cateory中的方法,然后调用本类方法,最后调用父类方法。
注意:category是在运行时加载的,不是在编译时。

为什么category不能添加成员变量?

Objective-C类是由Class类型来表示的,它实际上是一个指向objc_class结构体的指针。它的定义如下:

`typedef struct objc_class *Class;`

objc_class结构体的定义如下:

`struct objc_class {`

`Class isa  OBJC_ISA_AVAILABILITY;`

`#if !__OBJC2__`

`Class super_class                       OBJC2_UNAVAILABLE;  ``// 父类`

`const char *name                        OBJC2_UNAVAILABLE;  ``// 类名`

`long version                            OBJC2_UNAVAILABLE;  ``// 类的版本信息,默认为0`

`long info                               OBJC2_UNAVAILABLE;  ``// 类信息,供运行期使用的一些位标识`

`long instance_size                      OBJC2_UNAVAILABLE;  ``// 该类的实例变量大小`

`struct objc_ivar_list *ivars            OBJC2_UNAVAILABLE;  ``// 该类的成员变量链表`

`struct objc_method_list **methodLists   OBJC2_UNAVAILABLE;  ``// 方法定义的链表`

`struct objc_cache *cache                OBJC2_UNAVAILABLE;  ``// 方法缓存`

`struct objc_protocol_list *protocols    OBJC2_UNAVAILABLE;  ``// 协议链表`

`#endif`

`} OBJC2_UNAVAILABLE;`

在上面的objc_class结构体中,ivars是objc_ivar_list(成员变量列表)指针;methodLists是指向objc_method_list指针的指针。在Runtime中,objc_class结构体大小是固定的,不可能往这个结构体中添加数据,只能修改。所以ivars指向的是一个固定区域,只能修改成员变量值,不能增加成员变量个数。methodList是一个二维数组,所以可以修改*methodLists的值来增加成员方法,虽没办法扩展methodLists指向的内存区域,却可以改变这个内存区域的值(存储的是指针)。因此,可以动态添加方法,不能添加成员变量。

category中能添加属性吗?

这个我们要从Category的结构体开始分析:

`typedef struct category_t {`

`const char *name;  ``//类的名字`

`classref_t cls;  ``//类`

`struct method_list_t *instanceMethods;  ``//category中所有给类添加的实例方法的列表`

`struct method_list_t *classMethods;  ``//category中所有添加的类方法的列表`

`struct protocol_list_t *protocols;  ``//category实现的所有协议的列表`

`struct property_list_t *instanceProperties;  ``//category中添加的所有属性`

`} category_t;`

从Category的定义也可以看出Category的是可以添加实例方法,类方法,协议和属性的,但是无法添加成员变量。
所以category是可以添加属性的,但是用@property添加的属性只会生成getter和setter方法的声明,不会生成getter和setter方法的实现和成员变量。
但是可以通过Runtime的关联对象在getter和setter方法中实现。

注意:

extension:

什么是extension:

extension被开发者称之为扩展、延展、匿名分类。extension看起来很像一个匿名的category,但是extension和category几乎完全是两个东西。和category不同的是extension不但可以声明方法,还可以声明属性、成员变量。extension一般用于声明私有方法,私有属性,私有成员变量。

extension的存在形式:

category是拥有.h文件和.m文件的东西。但是extension不然。extension只存在于一个.h文件中,或者extension只能寄生于一个类的.m文件中。比如,viewController.m文件中通常寄生这么个东西,其实这就是一个extension:

@interface ViewController ()

@end
当然我们也可以创建一个单独的extension文件,如下图: image.png image.png image.png
UIView_extension.h中声明方法: image.png
导入UIView_extension.h文件进行使用: image.png

注意:

extension常用的形式并不是以一个单独的.h文件存在,而是寄生在类的.m文件中。

category和extension的区别:

上一篇 下一篇

猜你喜欢

热点阅读