iOS 分类 category(一)

2020-04-27  本文已影响0人  萨缪

今天要做的事有很多呢

Category是Objective-C 2.0之后添加的语言特性,分类、类别其实都是指的Category。Category的主要作用是为已经存在的类添加方法。
Objective-C 中的 Category 就是对装饰模式的一种具体实现。它的主要作用是在不改变原有类的前提下,动态地给这个类添加一些方法。
分类优点

声明私有方法
分解体积庞大的类文件
把Framework私有方法公开
模拟多继承(另外可以模拟多继承的还有protocol)

Category源码:
Category 是表示一个指向分类的结构体的指针,其定义如下:

typedef struct objc_category *Category;
struct objc_category {
char *category_name OBJC2_UNAVAILABLE; // 分类名
char *class_name OBJC2_UNAVAILABLE; // 分类所属的类名
struct objc_method_list *instance_methods OBJC2_UNAVAILABLE; // 实例方法列表
struct objc_method_list *class_methods OBJC2_UNAVAILABLE; // 类方法列表
struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; // 分类所实现的协议列表
}

结构体主要包含了分类定义的实例方法与类方法,其中instance_methods 列表是 objc_class 中方法列表的一个子集,而class_methods列表是元类方法列表的一个子集。
实现原理

1.我们不主动引入 Category 的头文件,Category 中的方法都会被添加进主类中。我们可以通过 - performSelector: 等方式对 Category 中的相应方法进行调用:
a)将 Category 和它的主类(或元类)注册到哈希表中;
b)如果主类(或元类)已实现,那么重建它的方法列表。

2.在这里分了两种情况进行处理:
a)Category 中的实例方法和属性被整合到主类中;
b)类方法则被整合到元类中
c)对协议的处理比较特殊,Category 中的协议被同时整合到了主类和元类中。

3.最终都是通过调用 staticvoid remethodizeClass(Class cls) 函数来重新整理类的数据的。

分类特点

1.分类是用于给原有类添加方法的,因为分类的结构体指针中,没有属性列表,只有方法列表。原则上讲它只能添加方法, 不能添加属性(成员变量),实际上可以通过其它方式添加属性 ;

2.分类中的可以写@property, 但不会生成setter/getter方法, 也不会生成实现以及私有的成员变量,会编译通过,但是引用变量会报错;

3.如果分类中有和原有类同名的方法, 会优先调用分类中的方法, 就是说会忽略原有类的方法,同名方法调用的优先级为 分类 > 本类 > 父类;

4.如果多个分类中都有和原有类中同名的方法, 那么调用该方法的时候执行谁由编译器决定;编译器会执行最后一个参与编译的分类中的方法。

5.运行时决议

6.同名分类方法生效取决于编译顺序

7.名字相同的分类会引起编译报错

在分类中,给分类添加成员变量实际上是添加属性:

示例代码

import <objc/runtime.h>

/* ---------------.h---------------*/
@interface NSString (url)
@property (nonatomic, retain) NSString *url;
@end

/* ---------------.m---------------*/
static char imageURLKey;
@implementation NSString (url)

objc_getAssociatedObject

这个函数先根据对象地址在 AssociationsHashMap 中查找其对应的 ObjectAssociationMap 对象,如果能找到则进一步根据 key 在 ObjectAssociationMap 对象中查找这个 key 所对应的关联结构 ObjcAssociation ,如果能找到则返回 ObjcAssociation 对象的 value 值,否则返回 nil;

objc_getAssociatedObject有两个参数,第一个参数为从该object中获取关联对象,第二个参数为想要获取关联对象的key;

/**

objc_setAssociatedObject

参数说明:

object和key同于objc_getAssociatedObject;

value:需要和object建立关联引用对象的value;

policy:关联策略,等同于给property添加关键字

/**

与分类相似的还有一个扩展:
扩展

声明私有属性

声明私有方法

声明私有成员变量

编译时决议

只以声明存在,寄生于宿主类.m中

不能为系统类添加扩展

类扩展优缺点分析

① 类扩展的属性和方法都是私有的,也可以定义在.h中,这样就是共有的,类扩展中的方法是一定要实现的方法。Category没有这个限制。
分类、扩展区别

category、extension异同点分析
1、分类(category)
① category只能添加“方法”,不能添加成员变量。
② 分类中可以访问原来类中的成员变量,但是只能访问@protect和@public属性。
③ 添加方法加上前缀,添加方法会覆盖父类的同名方法,可以防止意外覆盖,也防止被别人覆盖。
④ 分类中添加的成员变量,要通过getter、setter方法进行添加。

类扩展(extension)
① 类扩展的属性和方法都是私有的,也可以定义在.h中,这样就是共有的,类扩展中的方法是一定要实现的方法。Category没有这个限制。

上一篇下一篇

猜你喜欢

热点阅读