一、Category
Category在iOS开发中使用频繁,尤其在为系统类进行拓展的时候,我们可以不用继承系统类,直接给系统类添加方法,最大程度体现了Objective-C的动态语言特性。
注意事项
1:类别是类的扩展,只可以声明方法,不可以声明变量(runtime搞)。并且,类别的方法优先级较高,可覆盖原类方法。
2:类别的方法中,不可以调用super方法。--类别的局限
3:category 方法不能覆盖于同一class 的其它 category中的方法。因为不法预知他们的加载优先顺序,就可能在编译时出错。
使用类别:
1。对框架提供类的扩展(没有源码,不能修改)。
2。 不想生成一个新的子类的情况下,比如对NSArray 的扩展。
3。方便做项目管理,可以将一份源码在多个地方共享或者做方法版本管理、多人协作开发、用本地版本替换公共版本实现。
#import
@interface NSObject (Category)
- (void)myMethod;
@end
使用Category需要注意的点:
1.Category的方法不一定非要在@implementation中实现,也可以在其他位置实现,但是当调用Category的方法时,依据继承树没有找到该方法的实现,程序会崩溃。
2.Category理论上不能添加变量,但是可以使用@dynamic来弥补这种不足。
2.1 @dynamic的作用就是禁止编译器为@property产生setter和getter方法,有两种办法实现setter和getter方法 1.自己提供setter和getter方法;2.方法动态决议(DynamicMethod Resolution)dynamic参考链接http://blog.csdn.net/daydreamingboy/article/details/22682851
扩展@synthesize的作用就是让编译器自动生成setter和getter方法,还有一个作用,可以指定与属性对应的实例变量,例如@synthesize myButton = xxx; 那么self.myButton其实是操作的实例变量xxx,而不是_myButton了。
实际项目中有这么写的
@synthesize myButton;
这样写了之后,那么编译器会自动生成myButton的实例变量,以及相应的getter和setter方法。注意:_myButton这个实例变量是不存在的,因为自动生成的实例变量为myButton而不是_myButton,所以现在@synthesize的作用就相当于指定实例变量;
如果.m文件中写了@synthesize myButton;那么生成的实例变量就是myButton;如果没写@synthesize myButton;那么生成的实例变量就是_myButton
#import
static const voidvoid * externVariableKey =&externVariableKey;
@implementation NSObject (Category)
@dynamic variable;
- (id) variable
{
return objc_getAssociatedObject(self, externVariableKey);
}
- (void)setVariable:(id) variable
{
objc_setAssociatedObject(self, externVariableKey, variable, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
}
增加属性方法
.h文件
//分类的头文件
@interface ClassName (CategoryName)
@property (nonatomic, strong) NSString *str;
@end
.m文件
//实现文件
#import "ClassName + CategoryName.h"
#import <objc/runtime.h>
static void *strKey = &strKey;
@implementation ClassName (CategoryName)
-(void)setStr:(NSString *)str
{
objc_setAssociatedObject(self, & strKey, str, OBJC_ASSOCIATION_COPY);
}
-(NSString *)str
{
return objc_getAssociatedObject(self, &strKey);
}
@end
在setStr:
方法中使用了一个objc_setAssociatedObject
的方法,这个方法有四个参数,分别是:源对象,关联时的用来标记是哪一个属性的key(因为你可能要添加很多属性),关联的对象和一个关联策略。
用来标记是哪一个属性的key常见有三种写法,但代码效果是一样的,如下:
//利用静态变量地址唯一不变的特性
1、static void *strKey = &strKey;
2、static NSString *strKey = @"strKey";
3、static char strKey;
关联策略是个枚举值,解释如下:
enum {
OBJC_ASSOCIATION_ASSIGN = 0, //关联对象的属性是弱引用
OBJC_ASSOCIATION_RETAIN_NONATOMIC = 1, //关联对象的属性是强引用并且关联对象不使用原子性
OBJC_ASSOCIATION_COPY_NONATOMIC = 3, //关联对象的属性是copy并且关联对象不使用原子性
OBJC_ASSOCIATION_RETAIN = 01401, //关联对象的属性是copy并且关联对象使用原子性
OBJC_ASSOCIATION_COPY = 01403 //关联对象的属性是copy并且关联对象使用原子性
};
http://www.jianshu.com/p/3cbab68fb856
类别几个作用:
- 扩展已有的类。
- 引用父类未公开方法。
- 实现简单协议。
http://www.jianshu.com/p/2bf61807b6b3
二、Extension
Extension非常像是没有命名的类别,即匿名类别
作用:
1.能为某个类附加额外的属性,成员变量,方法声明
2.一般的扩展写到.m文件中(@implementation的上方)
3.一般的私有属性写到类扩展
使用格式
@interface Mitchell()
//属性
//方法
@end
使用Extension注意的点:
Extension中的方法必须在@implementaion中实现,否则编译会报错。