类别使用场景
-
见解一
Category的主要作用是为已经存在的类添加方法。
Objective-C 中的 Category 就是对装饰模式的一种具体实现。它的主要作用是在不改变原有类的前提下,动态地给这个类添加一些方法。 -
见解二
Category类别是Objective-C语言中提供的一个灵活的类扩展机制。类别可以在不获悉、不改变原来代码的情况下往一个已经存在的类中添加新的方法。类别只能添加新的扩展方法,而不能添加新的属性。类别扩展的新方法有更高的优先级,会覆盖同名的原类的已有方法。
优点
- 声明私有方法
- 分解体积庞大的类文件
- 把Framework私有方法公开
- 模拟多继承(另外可以模拟多继承的还有protocol)
- 当你在使用基础类库中的类时,你不想继承这些类而只想添加一些方法时。
- 相对于子类继承扩展,类别的另一明显优势是实现了功能的局部化封装,扩展的功能只会在本类被引用时看到。例如,假设原类为UIButton,现在要使用类别扩展一些用于模块A的方法,那么这些扩展方法就可以定义在一个叫做UIButton+A.h的头文件中,只有在引用UIButton+A.h的地方,才能看到原UIButton类有模块A添加的那些扩展方法,如果不需要模块A的功能,不引用UIButton+A.h头文件就看不到UIButton的那些扩展方法的存在,实现扩展模块的隔离。
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; // 分类所实现的协议列表
}
我们可以看到,他是有实例方法列表,类方法列表,但是就是没有属性列表。
所以,原则上它只能增加方法,不能增加成员(实例)变量。如果要扩展类的属性,OC作为一个有动态性的语言,用到运行时编程,必须使用<obj/runtime.h>,使用objc_getAssociatedObject,objc_setAssociatedObject以及objc_removeAssociatedObjects.
扩展类别(Category)属性
示例代码如下:
1、先创建一个person类
#import <Foundation/Foundation.h>
@interface Person : NSObject
@property (nonatomic, copy) NSString *name;
@end
#import "Person.h"
@implementation Person
@end
2、新建一个分类,运用associative添加属性
#import "Person.h"
@interface Person (addproty)
@property(nonatomic, copy)NSString *addr;
@end
#import "Person+addproty.h"
#import <objc/runtime.h>
@implementation Person (addproty)
static char strAddrKey = 'a';
- (NSString *)addr
{
return objc_getAssociatedObject(self, &strAddrKey);
}
- (void)setAddr:(NSString *)addr
{
objc_setAssociatedObject(self, &strAddrKey, addr, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
category、extension区别
- 分类中原则上只能增加方法(能添加属性的的原因只是通过runtime解决无setter/getter的问题而已);
- 类扩展的方法是一定要实现的方法。Category没有这个限制。这是因为类扩展是在编译阶段被添加到类中,而类别是在运行时添加到类中。
- Category的方法不一定非要在@implementation中实现,也可以在其他位置实现,但是当调用Category的方法时,依据继承树没有找到该方法的实现,程序则会崩溃。