iOS 分类和扩展
分类 Category
分类(Category)是OC中的特有语法,它是表示一个指向分类的结构体的指针。原则上它只能增加方法,不能增加成员(实例)变量。
分类 Category 属性和成员变量
在分类中可以写@property, 但是不会生成setter/getter方法,也不会实现成员变量。如果强制使用会报错。
不过可以通过runtime的关联对象的方法在Category使用成员变量
新建PersonModel文件
// PersonModel.h
@interface PersonModel : NSObject
@property (assign, nonatomic) int age;
@end
// PersonModel.m
#import "PersonModel.h"
@implementation PersonModel
@end
为PersonModel创建Category
// PersonModel+Category.h
@interface PersonModel (Category)
@property (copy, nonatomic) NSString *name;
@property (copy, nonatomic) NSString *objName;
@end
// PersonModel+Category.m
#import "PersonModel+Category.h"
#import <objc/runtime.h>
static NSString *objNameKey = @"objNameKey";
@implementation PersonModel (Category)
- (void)setObjName:(NSString *)objName
{
objc_setAssociatedObject(self, &objNameKey, objName, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
- (NSString *)objName
{
return objc_getAssociatedObject(self, &objNameKey);
}
@end
使用
PersonModel *person = [PersonModel new];
person.age = 10;
NSLog(@"person age = %d",person.age);
// 复值失败,因为Category只是添加了属性,没有添加成员变量
// person.name = @"jack";
// NSLog(@"person name = %@",person.name);
person.objName = @"jack";
NSLog(@"person objName = %@",person.objName);
返回
person age = 10
person objName = jack
分类 Category 同名方法执行顺序
同名方法执行顺序为 分类 > 本类 > 父类
如果多个分类和本类有同名的方法,调用该方法的时候执行由编译器决定。
在RootController
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"name = %@",self);
}
为RootController创建Category
- (void)viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
NSLog(@"Category name = %@",self);
}
返回
Category name = <RootController: 0x12df0ec90>
扩展
Extension:扩展, 延展, 匿名分类;放在.m文件中。一般用于声明私有属性(不对子类暴露)、声明私有方法、声明私有成员变量。
创建PersonModel的Extension - PersonModel+Ex
@interface PersonModel ()
@property (copy, nonatomic) NSString *exStr;
- (void)exDemo;
@end
在PersonModel.m里处理exStr和exDemo
- (void)exDemo
{
PersonModel *model = [PersonModel new];
model.exStr = @"Ex";
NSLog(@"ex = %@",model.exStr);
}
分类和扩展的区别
分类(Category) | 扩展(Extension) |
---|---|
运行时决议 | 编译时决议 |
有单独的.h和.m文件 | 以声明的方式存在,寄生于宿主类的.m文件 |
可以为系统类添加分类 | 不能为系统类添加扩展 |
看不到源码的类可以添加分类 | 没有.m源码的类无法为其添加扩展 |
Github地址
懒得打的可以直接打开项目查看
Github地址 https://github.com/HahnLoving/iOS_Study