OC 的分类(类别)和扩展基本上是面试必问的一个知识点,它们在日常开发中用的也非常多,相关文章网上非常多,好多都是一样的内容,本文也不免俗,按我自己的整理记录一下这个知识点
分类/类别(Category)
分类能够做到的事情主要是:即使在你不知道一个类的源码情况下,向这个类添加扩展的方法,通过分类可以将庞大一个类的方法进行划分,从而便于代码的日后的维护、更新以及提高代码的阅读性,那么怎么样新建一个分类呢?
在项目工程里使用快捷键 Command
+ N
新建文件,选择 Objective-C File
然后在 File
给这个分类的取个名字, File Type
选择 Category
,Class
选择你需要为那个类新建一个分类
之后就创建好了一个叫 NSString+Utility
的分类
|
|
然后我们就可以在这个分类里添加方法,既然叫 Utility
那么我就添加一个 NSString
相关的工具方法,比如增加一个给字符串 MD5 加密的方法
|
|
分类写好之后,在需要使用分类的文件里 #import "NSString+Utility.h"
就可以使用分类里面的方法了
使用分类需要注意
- 分类不能为已存在的类添加属性和实例变量,但是分类可以访问原来类中的成员变量
- 如果分类和原来类出现同名的方法, 优先调用分类中的方法, 原来类中的方法会被忽略
- 类别可以被继承,如果一个父类中定义了类别,那么其子类中也会继承此类别
- 在实际开发中要注意的是,分类的方法可能会覆盖于同一个类的其它分类中的方法,但也可能被覆盖,因为不法预知他们的加载优先顺序,出现这种情况通常会在编译时出错,如果在一个开发的SDK中使用了分类, 就最好保证分类名不同于使用者的分类名以及分类方法也不同于使用者的分类方法名,看过开源框架就知道,通常是通过加前缀来区分
虽然默认情况下,我们不能为分类添加属性和成员变量,但是,如果我们一定要为分类添加属性和成员变量也是可以的,这就需要用到 Runtime
里面的 objc_getAssociatedObject / objc_setAssociatedObject
来访问和生成关联对象
继续用上面的分类 NSString+Utility.h
举例,往这个分类里面添加一个 extensionName
属性
|
|
成员变量和属性的区别
声明一个属性:
1 @property (nonatomic, strong) NSString *myString;声明一个成员变量(实例变量):
123456 @interface ViewController : UIViewController{NSString *_myString;}@end我们声明了一个属性,因为现在我们用的编译器已经是LLVM了,所以不再需要为属性声明实例变量了。如果LLVM发现一个没有匹配实例变量的属性,它将为你生成以下划线开头的实例变量_myString,不需要自己手动再去写实例变量。而且也不需要在.m文件中写@synthesize myString;也会自动为你生成setter,getter方法 @synthesize的作用就是让编译器为你自动生成setter与getter方法。那么在.m文件中可以直接的使用 _myString 实例变量,也可以通过属性self.myString.两者都是一样的,只不过后者是通过调用_myString的setter/getter方法
@synthesize 还有一个作用,可以指定与属性对应的实例变量,例如@synthesize myString= xxxx;
那么self.myString其实是操作的实例变量xxxx,而不是_myString了分类中用@property定义变量,只会生成变量的getter,setter方法的声明,不能生成方法实现和带下划线
的成员变量
类扩展(Extension)
类扩展(Extension)是 Category
的一个特例,有时候也被称为匿名分类,它的作用是为一个类添加一些私有的成员变量和方法,使用类扩展的方法必须在 @implementation
中实现,否则编译会报错
类扩展看起来有点复杂,类扩展即可以声明成员变量又可以声明方法,其实我们很早就已经使用过类扩展了,先看一下类扩展的写法
|
|
类扩展通常定义在 .m 文件中,这种扩展方式中定义的变量和方法都是私有的,当然也可以定义在 .h 文件中,这样定义的变量和方法就是共有的都可以访问和使用,类扩展在 .m 文件中声明私有方法和私有变量是非常好的方式,现在自动生成的 .m 文件的上面都自带扩展了
|
|
当然我们也可以参照上面的新建分类的的方法用单独的文件定义类扩展,只是 File Type
选择 Extension
,生成的类扩展文件名格式为:主类名_扩展名.h
,类扩展文件只有 .h 文件,没有 .m 文件,我们在主类的 .m 文件中 #import
该类扩展文件,并且在主类的 .m文件中实现类扩展文件声明的方法,看看具体怎么实现
首先,新建了一个 ViewController
的类扩展文件 ViewController_ExtensionController.h
,代码如下
|
|
然后,在 ViewController
引入该类扩展文件,并且实现类扩展文件中声明的方法
|
|
类扩展需要注意
- 类扩展是类的一部分,在编译器和头文件的
@interface
和实现文件里的@implement
一起形成了一个完整的类 - 类扩展伴随着类的产生而产生,也随着类的消失而消失。
- 类扩展一般用来隐藏类的私有消息,你必须有一个类的源码才能添加一个类的
Extension
,所以对于系统一些类,如NSString
,就无法添加类扩展
以上就是 OC 中分类(类别)和扩展的介绍
本人刚开始写博客,主要是为了给自己的知识点做一个笔记,方便自己以后查阅,如果能让别人有所启发也是荣幸之至!如有错误,欢迎指正!