iOS技术点每日一篇程序员

iOS类别(Category)与扩展(Extension,匿名类

2017-03-07  本文已影响312人  _YZG_

一、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

类别几个作用:

二、Extension

Extension非常像是没有命名的类别,即匿名类别
作用:
1.能为某个类附加额外的属性,成员变量,方法声明
2.一般的扩展写到.m文件中(@implementation的上方)
3.一般的私有属性写到类扩展

使用格式

@interface Mitchell()
//属性
//方法
@end

使用Extension注意的点:
Extension中的方法必须在@implementaion中实现,否则编译会报错。

三、Category和Extension区别

区别.png
上一篇 下一篇

猜你喜欢

热点阅读