美文网首页
类别的高级玩法(Category)

类别的高级玩法(Category)

作者: WolfTin | 来源:发表于2017-08-10 16:18 被阅读0次

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;
}

相关文章

网友评论

      本文标题:类别的高级玩法(Category)

      本文链接:https://www.haomeiwen.com/subject/lnmhrxtx.html