分类是什么
分类是一种不需要继承即可给类添加方法的语法技术。可以在不改变原有类的前提下,动态地给这个类添加一些方法。
使用场景
1.给现有的类添加方法;
2.将一个类的实现拆分成多个独立的源文件;
3.声明私有的方法。
优点
a)可以减少单个文件的体积
b)可以把不同的功能组织到不同的category里
c)可以由多个开发者共同完成一个类
d)可以按需加载想要的category 等等。
注意事项
a)分类中只能添加“方法”,不能增加成员变量。
b)分类中可以访问原来类中的成员变量,但是只能访问@protect和@public形式的变量。如果想要访问本类中的私有变量,分类和子类一样,只能通过方法来访问。
c)如果一定要在分类中添加成员变量,可以通过getter,setter手段进行添加如何使用
- 扩展是什么
类扩展(extension)是category的一个特例,有时候也被称为匿名分类。他的作用是为一个类添加一些私有的成员变量和方法。
其实我们经常使用到类扩展, 当我们创建一个新的控制器的时候 会出现下面的代码段 :
@interface STWebViewController ()//这就是类扩展的写法
@property (nonatomic, strong) UIWebView *webView;
- (void)setUrl;
@end
类扩展可以定义在.m文件中,这种扩展方式中定义的变量都是私有的,也可以定义在.h文件中,这样定义的代码就是共有的,类扩展在.m文件中声明私有方法是非常好的方式。不过类扩展中添加的新方法,一定要实现。categorygory中没有这种限制。
- 拓展问题
a) 从上面内容了解到,分类只能添加方法。那么能不能添加成员变量呢,或者增加属性呢?
Object-c中,Category是不支持直接添加属性的,不过这不是很严谨,如果需要添加新的属性还是可以添加的,使用Runtime中的关联对象技术就可以实现。
还是先来了解一下,为什么分类不能添加成员变量吧 :
常规来说,在类中使用@property进行属性声明,编译器会自动生成getter和setter方法。但是在Category的指针结构体当中是没有属性列表的(ps : 指针结构体可以了解一下runtime机制,https://blog.csdn.net/jzl046/article/details/81389224),所以当你在Category中使用@property创建属性的时候编译器是不会帮你生成getter和setter方法,编译的时候不会出现问题,但是run了之后就会崩溃。
不过,由于OC是动态语言,方法真正的实现是通过runtime完成的,虽然系统不给我们生成setter/getter,但我们可以通过runtime手动添加setter/getter方法。
具体添加步骤如下 :
分类.h
#import "Programmer.h"
@interface Programmer (Category)
@property(nonatomic,copy) NSString *nameWithSetterGetter; //设置setter/getter方法的属性
- (void) programCategoryMethod; //分类方法
@end
分类.m
#import "Programmer+Category.h"
#import <objc/runtime.h>
static NSString *nameWithSetterGetterKey = @"nameWithSetterGetterKey"; @implementation Programmer (Category)
- (void)setNameWithSetterGetter:(NSString *)nameWithSetterGetter {
objc_setAssociatedObject(self, &nameWithSetterGetterKey, nameWithSetterGetter, OBJC_ASSOCIATION_COPY);
}
- (NSString *)nameWithSetterGetter {
return objc_getAssociatedObject(self, &nameWithSetterGetterKey);
}
- (void)programCategoryMethod {
NSLog(@"实现分类方法");
}
@end
这样就可以使用nameWithSetterGetter这个属性了