1. Category(分类/类别/类目)
通过Category可以很方便的为已经封装好的类添加新方法。
1.1 Category的创建和命名
创建Category会生成.h
和.m
两个文件.
// .h文件
#import <Foundation/Foundation.h>
@interface NSString (Addition)
@end
// .m文件
#import "NSString+Addition.h"
@implementation NSString (Addition)
@end
Category的命名常用 本类名 + 用途
格式,不继承父类,仅在括号中表明此分类的主要用途。
1.2 Category的使用场景
- 对现有类进行扩展
通过Category增加的方法,会成为本类的一部分,与本类的其他方法的调用没有区别;
通过Category增加的方法,会被子类所继承,而父类不会拥有子类的Category中的方法。 - 替代子类的部分功能
不需要新建子类,通过Category直接为已有的类增加方法。 - 对大类中的方法整理归纳
利用Category把一个庞大的类按功能划分为几个小分类,分别开发,便于更新、维护。
1.3 使用Category的注意点
- Category无法添加实例变量(属性)
只能通过新建子类的方式新增类的实例变量。(实际上也可以通过Runtime在分类中添加方法) - Category会覆盖本类中的同名方法
(方法调用优先级:分类 > 本类 > 父类),使用时需要谨慎。
2. Extension(延展)
OC2.0之后增加了Extension,可以为类添加额外的私有属性或私有方法,因此也把Extension称为匿名的Category。
2.1 Extension的创建
创建Extension仅生成.h
文件。
// .h文件
#import <Foundation/Foundation.h>
@interface NSString ()
@end
实际项目中,通常不会专门创建一个Extension文件,而是寄生在.m
文件中(在 .m
文件的 @interface
中定义,在 @implementation
中实现)
#import "PFWKWebView.h"
#import <WebKit/WebKit.h>
@interface PFWKWebView ()
// 私有属性
@property (nonatomic, strong) WKWebView *webView;
// 私有方法,只能在@implementation内部调用,外部不可见
- (void)setupUI;
@end
@implementation PFWKWebView
- (void)viewDidLoad {
[super viewDidLoad];
[self setupUI];
}
- (void)setupUI {
self.view.backgroundColor = UIColor.redColor;
}
PS:
注意,直接在 @interface
或 @implementation
后接的大括号定义成员变量的情况有所不同:
- 变量名要带
_
- 此时不会自动为变量生成setter/getter方法(即不能通过
self.
的方式访问,需要直接用_
访问)
#import "PFWKWebView.h"
#import <WebKit/WebKit.h>
@interface PFWKWebView () {
NSString *_name; // 姓名
}
@end
@implementation PFWKWebView {
NSString *_nickName; // 昵称
}
- (void)viewDidLoad {
[super viewDidLoad];
_name = @"名字";
_nickName = @"昵称";
}
3. Category和Extension的区别
- 生成的文件不同
新建Category会生成.h
和.m
两个文件,而新建Extension仅生成一个.h
文件。 - Category不能添加类属性,而Extension添加私有属性或变量。
- Category添加的方法会被子类继承,而Extension添加的方法、属性不能被子类继承(因为它们是private的)。
- Category可以为自定义的类或者framework框架中的类增加方法,而Extension只能为自定义的类添加方法(因为OC是闭源的,系统的
.m
方法不可见) - Category是
@interface 本类名 (分类名)
、@implementation 本类名(分类名)
,而Extension是@interface 本类名 ()
。
// Category .h文件
#import <Foundation/Foundation.h>
@interface NSString (Addition)
@end
// Category .m文件
#import "NSString+Addition.h"
@implementation NSString (Addition)
@end
// Extension .h文件
#import <Foundation/Foundation.h>
@interface NSString ()
@end
- 分类中在
.h
中声明、在.m
中实现的方法为公开方法,可被外部访问;Extension中的方法为私有方法、变量为私有变量,外界无法直接访问。
(OC中因为没有真正意义上的私有方法,所以可以通过选择器访问)。
(PS:如果公开方法、私有方法声明的方法名相同,经测试只要实现了该方法就是公开方法)。 - 可以把Extension理解为特殊的Category。