iOS开发之OC篇(12)—— Category(分类)、Extension(扩展)
2017-05-25 22:11
543 查看
版本
Xcode 8.3.2一、分类
Category这里称分类(另说类别、类目)。分类的作用:扩展已有类(包括系统类)的功能。比如给NSString增加一个字符串反转的方法。你可能想到了,用继承也可以增加这个功能。那为什么又搞出个分类呢?不妨来对比一下。
1、继承Inherit VS 分类Category
继承继承特点:
1)子类可以扩展自己特有的属性(包括新增成员变量),但是不能访问父类的私有成员变量。
2)子类可以扩展自己特有的方法,且新方法可以与原方法同名,而不会对父类原方法产生影响。
什么情况下使用继承?
1)扩展类的属性。
2)新扩展的方法与原方法同名,但是还需要使用父类的实现。
分类
分类特点:
1)分类可以在不改变类名和原有类的实现的前提下,进行类的扩展。
2)在方法内部可以访问原有类的成员变量(在头文件中定义的成员变量),不能给原有类增加成员变量(使用@property只能生成setter和getter方法的声明,不能生成方法的实现,也不会生成带“_”的成员变量)。可以给原有类添加属性:使用Runtime里的运行时关联对象方法来实现属性的setter和getter方法。
3)分类与原有类不能有同名的方法。因为这样会覆盖原类的实现,而无法访问到原来的方法。
4)分类之间也不能有同名的方法。因为最后编译的那个方法会覆盖其他方法。
什么情况下使用分类?
1)针对系统类(例如:NSString、NSArray、NSNumber等),系统本身不提倡使用继承去扩展方法,因为这些类内部实现对继承有所限制,所以应使用分类的方式扩展。
2)分类支持开发人员针对自己构建的类,把相关的方法分组到多个单独的文件中,对于大型而复杂的类,这有助于提高可维护性,并简化单个源文件的管理。
2、给分类添加方法
步骤:为原有类创建一个分类
在分类中增加新方法的声明和实现
按图:
1
2
3
4
注意到上图中的+Revers和(Revers),这些是固定格式,表过不提。
接下来贴上开头提到的字符串反转代码:
.h文件
#import <Foundation/Foundation.h> @interface NSString (Revers) // 字符串反转方法 -(NSString *)stringByReversString; @end
.m文件
#import "NSString+Revers.h" @implementation NSString (Revers) // 字符串反转方法 -(NSString *)stringByReversString { NSUInteger length = [self length]; NSMutableArray *array = [NSMutableArray arrayWithCapacity:length]; for(long i=length-1; i>=0; i--){ unichar c = [self characterAtIndex:i]; [array addObject:[NSString stringWithFormat:@"%c",c]]; } NSMutableString *str = [NSMutableString stringWithCapacity:length]; for(int i=0; i<=length-1; i++){ [str appendString:array[i]]; } return str; } @end
.main中调用:
#import <Foundation/Foundation.h> #import "NSString+Revers.h" int main(int argc, const char * argv[]) { NSString *str = @"abcde"; str = [str stringByReversString]; NSLog(@"%@",str); return 0; }
输出如下:
3、给分类添加属性
前文提到,分类添加属性,系统只能生成setter和getter方法的声明,不能生成方法的实现,也不会生成带“_”的成员变量。如果我们仍然想给分类添加可用的属性,那么可以使用Runtime里的运行时关联对象方法来实现属性的setter和getter方法。
关于Runtime的技术原理,请参考这里。
实现步骤如下:
1、.h文件中添加属性
#import <Foundation/Foundation.h> @interface NSString (Revers) @property (nonatomic, retain) NSNumber *tag; @end
2、导入Runtime头文件
#import <objc/runtime.h>
3、.m文件中实现属性的setter和getter方法
#import "NSString+Revers.h" #import <objc/runtime.h> static char tagKey; // 用来标记是哪一个属性的key(静态变量地址唯一且不变) @implementation NSString (Revers) // tag的setter方法 - (void)setTag:(NSNumber *)tag { // 注意第四个参数参数OBJC_ASSOCIATION_RETAIN_NONATOMIC是和属性修饰符对应的 objc_setAssociatedObject(self, &tagKey, tag, OBJC_ASSOCIATION_RETAIN_NONATOMIC); } // tag的getter方法 - (NSNumber *)tag { return objc_getAssociatedObject(self, &tagKey); } @end
4、调用属性示例
NSString *str = @"abcde"; str.tag = @101; NSLog(@"tag:%@",str.tag);
注意
Xcode中对objc_setAssociatedObject的定义如下。
objc_setAssociatedObject(id _Nonnull object, const void * _Nonnull key, id _Nullable value, objc_AssociationPolicy policy);
第三个参数(即要关联的数据类型)是id数据类型,而id类型是指向对象的指针,所以说,关联对象不能是基本数据类型(如BOOL、NSInteget、long等等)。当我们需要为分类添加基本数据类型的时候,可以先将基本数据类型转化成OC对象,再添加属性。
二、扩展
先来看看:1
2
3
注意到上图中的_Exs和(),这些是扩展固定格式,是不是感觉和分类有点相似呢?
其实,扩展也叫匿名分类,区别是扩展只有.h文件,而实现是写在被扩展类的.m文件中的。因此,扩展的功能可以认为是被扩展类所私有的,其他类无法使用。
扩展的作用:为类增加私有的属性和方法。一般不用于给系统类添加方法。
因为是私有属性和方法,我们一般不另外生成Extension(扩展)的.h文件,而是将.h文件里的内容(声明)直接写在被扩展类的.m文件里。
例如,我们要扩展一个自定义的Person类,不用另外创建Extension的.h文件,而是在Person的.m文件里加入:
@interface Person () { // 添加成员变量 NSString * _sex; } // 添加方法,实现要写在下方的@implementation里 - (void)sayHello; @end
相关文章推荐
- 【IOS开发技术】 Objective-C分类 (category)和扩展(Extension)
- iOS分类(category),类扩展(extension)—史上最全攻略
- iOS 分类(category)、扩展(Extension)
- iOS复习 OC语言 类目Category/类扩展Extension
- iOS分类(category),类扩展(extension)—史上最全攻略
- bruceyou1990-iOS学习日记-分类(Category) 和 扩展(Extension)
- iOS分类(Category)和类扩展(Extension)的简单区别
- ios 分类(category)和类扩展(extension)详解
- IOS 分类(category)、扩展(Extension)和继承(inheritance)的区别?
- iOS 使用分类category和扩展extension
- iOS分类(category),类扩展(extension)—史上最全攻略
- 黑马程序员——Objective-C分类 (category)和扩展(Extension)——黑马 ios 技术博客
- OC中分类(Category)和扩展(Extension)
- iOS类别(Category)与扩展(Extension,匿名类别)
- iOS开发之类别、扩展 分类: ios开发 2015-04-02 11:01 160人阅读 评论(0) 收藏
- iOS类别(Category)与扩展(Extension)
- OC中的类别Category-协议Protocol-扩展Extension
- IOS开发---OC语言-⑮分类
- iOS类别(Category)与扩展(Extension)
- iOS 键盘类型定制归纳 分类: ios开发 2015-04-02 12:58 347人阅读 评论(0) 收藏