iOS—分类、load 、initialize

Objective-C的Category允许在不修改原类源码的情况下扩展类的功能,本文深入探讨Category的结构、load和initialize的调用顺序及区别。详细解析了Category如何在运行时合并方法、属性和协议,以及为何不能添加成员变量,同时介绍了使用关联对象的场景。此外,对比了Category与类扩展(Extension)的异同。
摘要由CSDN通过智能技术生成


写的有些乱…

分类

Category分类是Objective-C 2.0添加的语言特性,主要作用是为已经存在的类添加方法。Category可以做到在既不子类化,也不侵入一个类的源码的情况下,为原有的类添加新的方法,从而实现扩展一个类或者分离一个类的目的。

通常Category有以下几种使用场景

  • 把类的不同实现方法分开到不同的文件里
  • 可以由多个开发者共同完成一个类
  • 声明私有方法
  • 模拟多继承
  • 将framework私有方法公开化

分类的结构

struct _category_t {
   
	const char *name;	        //分类所属的类名
	struct _class_t *cls;
	const struct _method_list_t *instance_methods;   //实例方法
	const struct _method_list_t *class_methods;   //类方法
	const struct _protocol_list_t *protocols;    //协议
	const struct _prop_list_t *properties;       //属性
};

将新建的分类的.m文件,转为c++,就可以看到 上面分类的底层结构,_category_t结构体

_category_t结构体定义了一个结构体变量
变量名有些长 _OBJC_$_CATEGORY_Person_$_Test

static struct _category_t _OBJC_$_CATEGORY_Person_$_Test __attribute__ ((used, section ("__DATA,__objc_const"))) = 
{
   
	"Person",
	0, // &OBJC_CLASS_$_Person,
	(const struct _method_list_t *)&_OBJC_$_CATEGORY_INSTANCE_METHODS_Person_$_Test,
	(const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Test,
	(const struct _protocol_list_t *)&_OBJC_CATEGORY_PROTOCOLS_$_Person_$_Test,
	(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_Person_$_Test,
};

后面是对_category_t结构体类型变量_category_t OBJCKaTeX parse error: Expected group after '_' at position 17: …CATEGORY_Person_̲_Test的赋值。
对比分类结构体的定义

  • 第一个成员,“Person”,分类所属的类名
  • 第二个,都设为0
  • 第三个成员,(const struct _method_list_t *)&_OBJC_$_ CATEGORY_INSTANCE_METHODS_Person_$_Test
    这个也是一个结构体变量,存储着实例方法,如图
    在这里插入图片描述
    实例方法test的实现
    在这里插入图片描述
  • 第四个成员,(const struct _method_list_t *)&_OBJC_$_CATEGORY_CLASS_METHODS_Person_$_Test
    也是一个结构体变量,存储着类方法,如图
    在这里插入图片描述
    类方法test1的实现
    在这里插入图片描述
    在分类中,如果实现了对象方法、类方法,都会添加到对应的方法列表结构体中。
    但如果仅仅定义、没有实现,就不会加进来
  • 第五个成员,(const struct _protocol_list_t *)&_OBJC_CATEGORY_PROTOCOLS_$_Person_$_Test
    协议相关的结构体变量,Test分类中我遵循了NSCopying协议
    在这里插入图片描述
    这个结构体中包含了一个_protocol_t结构体数组
    _protocol_t的定义如下
    在这里插入图片描述
    _OBJC_PROTOCOL_NSCopying的赋值如下
    在这里插入图片描述
  • 第六个成员,(const struct _prop_list_t *)&_OBJC_$_PROP_LIST_Person_$_Test
    属性相关的结构体变量,Test分类中,写了一个NSString类型的变量str
    在这里插入图片描述在这里插入图片描述

当类中有一个方法,多个分类中有相同的方法,调用这个方法一定执行的是分类中的方法,具体是哪一个分类就要看编译时的顺序,在attachCategories方法中 对分类列表进行倒序遍历 将分类包含的方法列表、协议列表、属性列表分别合并到对应的大数组中,将合并好的分类数据插入到类原来的数据前面。
对分类列表的遍历是倒序,即最后参与编译的分类先被添加到方法列表的开始位置。
attachCategories(Class cls, category_list *cats, bool flush_caches)方法实现中
在这里插入图片描述
日志中eat先编译,打印是eat的方法????
在这里插入图片描述
上面那个应该不准 哈哈哈哈

控制编译顺序

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值