Category的简单介绍
作用及使用场景
Category的主要作用是为已经存在的类添加方法(包括实例方法和类方法,还有一点分类可以被继承的,子类可以使用父类的分类添加的方法)。除了这个基本的功能,Apple还推荐下面两个使用场景:
- Category可以把类的实现分开在几个不同的文件里面
这样做有几个显而易见的好处:
1、可以减少单个文件的体积
2、可以把不同的功能组织到不同的Category里
3、可以由多个开发者共同完成一个类
4、可以按需加载想要的Category 等等。
- 声明私有方法
还衍生出了Category的其他几个使用场景:
- 模拟多继承
- 把framework的私有方法公开
Objective-C的这个语言特性对于纯动态语言来说可能不算什么,比如javascript,你可以随时为一个“类”或者对象添加任意方法和实例变量。但是对于不是那么“动态”的语言而言,这确实是一个了不起的特性。
和Extension区别
Extension看起来很像一个匿名的Category,但是Extension和有名字的Extension几乎完全是两个东西。
Extension在编译期决议,它就是类的一部分,在编译期和头文件里的@interface
以及实现文件里的@implement
一起形成一个完整的类,它伴随类的产生而产生,亦随之一起消亡。
Extension一般用来隐藏类的私有信息,你必须有一个类的源码才能为一个类添加Extension,所以你无法为系统的类比如NSString添加Extension。
但是Category则完全不一样,它是在运行期决议的。
就Category和Extension的区别来看,我们可以推导出一个明显的事实,Extension可以添加实例变量,而Category是无法添加实例变量的(因为在运行期,对象的内存布局已经确定,如果添加实例变量就会破坏类的内部布局,这对编译型语言来说是灾难性的)。
简单使用
基本使用---为已经类添加方法
例:为UIScrollView添加方法
/********** .h文件 ***************/
#import <UIKit/UIKit.h>
@interface UIScrollView (Category)
//添加实例方法
- (void)exchangeMethodTest;
@end
/********** .m文件 ***************/
#import "UIScrollView+Category.h"
#import <objc/runtime.h>
@implementation NSObject (Category)
//为UIScrollView父类NSObject添加两个私有类方法
+ (void)exchangeInstanceMethod1:(SEL)method1 method2:(SEL)method2 {
method_exchangeImplementations(class_getInstanceMethod(self, method1), class_getInstanceMethod(self, method2));
}
+ (void)exchangeClassMethod1:(SEL)method1 method2:(SEL)method2 {
method_exchangeImplementations(class_getClassMethod(self, method1), class_getClassMethod(self, method2));
}
@end
@implementation UIScrollView (Category)
//为UIScrollView添加两个私有方法
- (void)method1 {
NSLog(@"method1");
}
- (void)method2 {
NSLog(@"method2");
}
//实现为UIScrollView添加的公共方法
- (void)exchangeMethodTest {
NSLog(@"我调用----method1");
[self method1];
[UIScrollView exchangeInstanceMethod1:@selector(method1) method2:@selector(method2)];
NSLog(@"方法交换IMP指针后,我再调用----method1");
[self method1];
}
@end
为已知类添加全局属性
例:为UIScrollView添加offsetX(横向偏移量),offsetY(纵向偏移量),contentW(content宽度),contentH(content高度)
/********** .h文件 ***************/
#import <UIKit/UIKit.h>
@interface UIScrollView (Category)
@property (nonatomic, assign) CGFloat offsetX;
@property (nonatomic, assign) CGFloat offsetY;
@property (nonatomic, assign) CGFloat contentW;
@property (nonatomic, assign) CGFloat contentH;
@end
/********** .m文件 ***************/
#import "UIScrollView+Category.h"
#import <objc/runtime.h>
@implementation UIScrollView (Category)
- (void)setOffsetX:(CGFloat)offsetX {
CGPoint offset = self.contentOffset;
offset.x = offsetX;
self.contentOffset = offset;
}
- (CGFloat)offsetX {
return self.contentOffset.x;
}
- (void)setOffsetY:(CGFloat)offsetY {
CGPoint offset = self.contentOffset;
offset.y = offsetY;
self.contentOffset = offset;
}
- (CGFloat)offsetY {
return self.contentOffset.y;
}
- (void)setContentW:(CGFloat)contentW {
CGSize size = self.contentSize;
size.width = contentW;
self.contentSize = size;
}
- (CGFloat)contentW {
return self.contentSize.width;
}
- (void)setContentH:(CGFloat)contentH {
CGSize size = self.contentSize;
size.height = contentH;
self.contentSize = size;
}
- (CGFloat)contentH {
return self.contentSize.height;
}
网友评论