iOS 分类和扩展的作用和区别

  • 分类即Category
    • 分类可以添加方法,也可以写添加属性,但是因为没有生成对应的成员变量和setter、getter方法,因此没有实际属性意义;
    • 分类里面不允许使用关键字@synthesize;
    • 将不同的功能分摊到不同的文件,减轻单个文件的体积;
    • 多人共同开发同一个类的不同分类,按需加载不同的分类;
struct category_t {
    const char *name;                             // 类名
    classref_t cls;                               // 类
    struct method_list_t *instanceMethods;        // 实例方法列表
    struct method_list_t *classMethods;           // 类方法列表
    struct protocol_list_t *protocols;            // 协议列表
    struct property_list_t *instanceProperties;   // 添加的属性列表
    // Fields below this point are not always present on disk.
    struct property_list_t *_classProperties
};

从上面可以看出分类可以添加实例方法、类方法、协议、属性,但是不能添加实例变量。

  • 扩展即Extension
    • 为某个类附加额外的属性、成员变量以及方法声明,因为一般是依附于.m文件里面,所以一般都是私有变量,当然也可以单独作为一个文件存在.h文件里面;
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;
  • extension是在编译器决定的,而category是在运行期决定的。
    在runtime 中,objc_class 结构体大小是固定的,不可能往这里添加数据,只能修改。所以,ivars 指向了一个固定区域,只能修改成员变量的值,不能增加成员变量的个数。方法列表是一个二维数组,可以修改 *methodLists的值来增加成员方法,虽然没办法扩展methodLists指向的内存区域,却可以改变这个内存区域的值(里面存的是指针),因此,可以动态添加方法,不可以添加成员变量。
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容