category && extension 介绍
1、category 分类
-
介绍
利用Objective-C的动态运行时分配机制,Category提供了一种比继承(inheritance)更为简洁的方法来对class进行扩展,无需创建对象类的子类就能为现有的类添加新方法,可以为任何已经存在的class添加方法,包括那些没有源代码的类(如某些框架类)。
-
原理
我们知道,所有的OC类和对象,在runtime层都是用struct表示的,category也不例外,在runtime层,category用结构体category_t(在objc-runtime-new.h中可以找到此定义),它包含了
-
类的名字(name)
-
类(cls)
-
category中所有给类添加的实例方法的列表(instanceMethods)
-
category中所有添加的类方法的列表(classMethods)
-
category实现的所有协议的列表(protocols)
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; }
-
-
特点
- 拆分类,降低类的复杂度
- 扩展类的方法,比如系统自带类
- 不能添加实例变量
-
使用 在h文件中添加方法,m文件中实现方法就ok了
2、extension 扩展
Extension常被称为是匿名的Category 用于给类添加新方法,但只作用于原始类,不作用于subclass 只能对有implementation源代码的类写Extension,对于没有implementation源代码的类,比如framework class,是不可以的 Extension可以给原始类添加新方法,以及新属性 类目(category)可以给系统已有类添加扩展方法但是不能添加属性,并且被添加的方法可以被此类的子类所继承;延展(extension)为我们的自定义类添加属性和方法,但是添加的属性和方法都是私有的,在此类的子类中是无法访问的。
extension在编译期决议,它就是类的一部分,在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加extension,所以你无法为系统的类比如NSString添加extension
但是category则完全不一样,它是在运行期决议的。
就category和extension的区别来看,我们可以推导出一个明显的事实,extension可以添加实例变量,而category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。
3、如何给category添加实例变量
重写set/get方法
- (NSString *)viewName { return (NSString *)objc_getAssociatedObject(self, viewNameKey);}// set方法- (void)setViewName:(NSString *)newViewNameKey { objc_setAssociatedObject(self, viewNameKey, newViewNameKey, OBJC_ASSOCIATION_RETAIN_NONATOMIC);}
为什么这样可以呢?
创建关联要使用到Objective-C的运行时函数:objc_setAssociatedObject来把一个对象与另外一个对象进行关联。