Category是什么
苹果官方关于category的文档在这里:官方文档
Category是对类进行扩展,得到的类叫做Category。
写在.m里面的,行如:
@interface ViewController ()
@end
叫做匿名分类。如果括号里有名称xxx的
@interface ViewController (xxx)
@end
这个叫分类就行了,不是匿名的,是有名称的。
匿名分类的存在是有意义的,我们一般在.m中不用写匿名分类的名称,就知道是该类的分类,在匿名分类中我们写一些属性之类的,这就是对该类进行扩展,扩展了些属性。很在的iOS开发中还有在匿名分类中申明方法的,也算是给该类扩展方法。
在Category是不能添加实例变量的,在.m的匿名分类中是可以的。Category是动态的给类添加方法,写在类内部的匿名分类不是动态的,是编译时作为类的一部分,和类一起编译的。
Category的作用
1、在不改变原有类的前提下,动态的给该类添加一些方法;
2、定义私有方法和属性;
3、可以将一个类的实现,拆分在不用的文件内实现。
使用Category
1、匿名分类的使用
匿名分类是我们经常使用的
@interface ViewController ()
{
NSUInteger _count;
}
@property (nonatomic , copy) NSString *viewId;
@end
给类增加私有属性,也可以在其中申明私有方法。
给类扩展全局的成员变量。
写在扩展中的属性,是私有的,如果类外部需要使用也是有办法的,属性修饰词readOnly、readWrite了解一下。
2、在分类的类中扩展属性
给一个类扩展方法和属性
扩展新方法就不用多说,主要说一下增加属性。
分类是不能给类扩展实例变量的,但是属性是可以的。需要注意的是,在分类的.h中写一个属性,系统不会自动生成set和get方法,因为分类是运行时决定的,所以需要我们手动给分类中的属性写set和get方法,例如:
@interface UIView (ViewFrameGeometry)
@property CGFloat height;
@property CGFloat width;
@end
@implementation UIView (ViewGeometry)
- (CGFloat) height
{
return self.frame.size.height;
}
- (void) setHeight: (CGFloat) newheight
{
CGRect newframe = self.frame;
newframe.size.height = newheight;
self.frame = newframe;
}
- (CGFloat) width
{
return self.frame.size.width;
}
- (void) setWidth: (CGFloat) newwidth
{
CGRect newframe = self.frame;
newframe.size.width = newwidth;
self.frame = newframe;
}
给一个类创建一个分类文件,生成.h和.m,其中.h形如:
@interface ViewController (UI)
@end
在分类的.m文件中,如果我们需要使用私有属性,怎么办?
首先在.m中写一个扩展,添加属性
@interface ViewController()
@property (nonatomic, copy) NSString *viewId;
@end
@implementation VHLiveViewController (UI)
@end
这样编译是不会报错的,但是在执行调用viewId这个属性时,就会crash。
这里需要了解一下runtime的动态绑定属性:
引入头文件:#import <objc/runtime.h>
写一个静态变量static NSString *viewIdKey = @“viewIdKey”;
给viewId这个属性,动态添加set和get方法:
- (void)setViewId:(NSString *)viewId{
objc_setAssociatedObject(self, &viewIdKey, viewId, OBJC_ASSOCIATION_RETAIN);
}
- (NSString *)viewId{
return objc_getAssociatedObject(self, &viewIdKey);
}
3、分类在类的实现上的应用
有一个类的实现特别复杂,将其拆成了若干分类,将不同功能定义在了不同的分类文件中实现。
在苹果的官方文档中我们可以看到大量的分类的使用,为了实现一个类的功能,增加分类,便于管理代码,也不会造成原来功能的问题,使得现有类的功能越来越强大。
Category使用须知
1、分类添加方法是动态添加的,分类中写原有类的方法,则会覆盖原有类的方法。
2、使用分类时,建议遵循一个原则就是不改变原有类的前提下使用,当然非得要改变也是有办法的。
3、分类可以添加新的方法,但是不能增加实例变量,在扩展中是可以添加实例变量的。
4、分类.h中添加属性,系统不会自动生成set和get方法。
5、分类是不能给类扩展实例变量的,属性是可以的,需要实现set和get方法。
Category和Extension
Extension是扩展,Category是分类,对类进行扩展,扩展出来的类叫做分类。
可以说分类是扩展的一种形式,是对类进行扩展,叫了个别名——分类。
分类是扩展的一种形式,是扩展在类上的应用。
扩展的定义比较广,不仅可以扩展类,还可以扩展别的。比如给主App扩展一个子App,主App是宿主App,子App是在宿主上扩展出来的,依赖于宿主的子App。
扩展肯定还有其他的用途,只是我暂时只能想到以上两种。
推荐阅读
选择性涉猎,不一定全对。
思考
以下是分类被用作其他方面:
-
利用category模拟多继承;
-
利用category将framework的私有方法公开。