category是Objective-C 2.0之后添加的语言特性,category的主要作用是为已经存在的类添加方法.
可以看下美图技术团队的这篇文章
1.创建Category
#import <Foundation/Foundation.h>
NS_ASSUME_NONNULL_BEGIN
@interface NSString (NSString_NumberConvenience)
-(NSNumber *)lengthAsNumber;
@end
NS_ASSUME_NONNULL_END
#import "NSString+NSString_NumberConvenience.h"
@implementation NSString (NSString_NumberConvenience)
- (NSNumber *)lengthAsNumber{
NSUInteger length = [self length];
return [NSNumber numberWithUnsignedInt:length];
}
@end
#import <Foundation/Foundation.h>
#import "NSString+NSString_NumberConvenience.h"
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
NSLog(@"字数 %@",@"白日依山尽".lengthAsNumber);
}
return 0;
}
//字数 5
2.优劣势
优势:
(1). 减少单个文件的体积
(2). 把不同的功能分配到不同的分类里,便于管理
(3). 可以按需加载想要的分类
局限性:
(1). 无法向类中添加新的实例变量
(2). 类别中的方法名与现有方法重名, 名称冲突.(冲突时,类别有更高的优先级)
3. category本质
我们知道,所有的OC类和对象,在runtime层都是用struct表示的,category也不例外,在runtime层,category用结构体category_t(在objc-runtime-new.h中可以找到此定义),它包含了:
1)、类的名字(name)
2)、类(cls)
3)、category中所有给类添加的实例方法的列表(instanceMethods)
4)、category中所有添加的类方法的列表(classMethods)
5)、category实现的所有协议的列表(protocols)
6)、category中添加的所有属性(instanceProperties)
从category的定义也可以看出category的可为(可以添加实例方法,类方法,甚至可以实现协议,添加属性)和不可为(无法添加实例变量)。
平常都是使用分类来对系统的类封装一些小功能,如NSString判空处理等,可以看下 ibireme大神开源的这个库YYCategories,都是针对系统的类使用分类拓展的小功能,很实用。再来看看业界闻名的空白页框架DZNEmptyDataSet,它就是通过对 UIScrollView
使用分类功能,非常完美、无侵入的解决了无数据时,避免白屏的尴尬,改善用户体验。
二. 类扩展(extension)
extension的别名有很多,扩展、延展、匿名分类。它就是类的一部分,在编译期和头文件里的@interface以及实现文件里的@implement一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。
我们平时在.m文件里使用的
@interface ViewController ()
//私有属性
//私有方法
@end
1. Extension的作用
声明私有属性
声明私有方法
声明私有成员变量
2. Extension的特点
编译时决议
只以声明的形式存在,多数情况下寄生在宿主类的.m中
一般的私有属性写到.m文件中的类扩展中
不能为系统类添加扩展
Category和Extension的区别
extension 在编译期决议, category在运行期决议。
- 分类是运行时决议;扩展是编译时决议;(所以扩展中声明的方法没有被实现,编译器会报警,但是分类种的方法没有被实现编译器是不会有任何警告的)
- 分类原则上只能增加方法,并且是公开的(无法直接添加属性,可以通过runtime添加属性,原因通过runtime可以解决无setter/getter的问题);扩展能添加方法,实例变量,默认是@private类型的,且只能作用于自身类,而不是子类或者其他地方;
- 分类有自己的实现部分;扩展无自己的实现部分,只能依托对应类的实现部分来实现;
- 分类可以为系统类添加分类;扩展不可以为系统类添加扩展(必须有一个类的源码才能添加一个类的Extension);所以你无法为系统的类比如NSString添加extension
定义在 .m 文件中的类扩展方法为私有的,定义在 .h 文件(头文件)中的类扩展方法为公有的。类扩展是在 .m 文件中声明私有方法的非常好的方式。
(详见(https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/CustomizingExistingClasses/CustomizingExistingClasses.html))