运行时
几个常见应用
1、交换方法的实现
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
@implementation UIImage (Image)
// 加载分类到内存的时候调用,在 init: 方法之前调用
+ (void)load {
// 交换方法
// 获取 imageWithName 方法地址
Method imageWithName = class_getClassMethod(self, @selector(imageWithName:));
// 获取 imageName 方法地址
Method imageName = class_getClassMethod(self, @selector(imageNamed:));
// 交换方法的实现
method_exchangeImplementations(imageWithName, imageName);
}
// 不能在分类中重写系统方法 imageNamed,因为会把系统的功能给覆盖掉,而且分类中不能调用 super
// 可以先对图片做某些处理
+ (instancetype)imageWithName:(NSString *)name {
// 这里调用 imageWithName,相当于调用 imageName 的实现。
UIImage *image = [self imageWithName:name];
if (image == nil) {
NSLog(@"加载空的图片");
}
return image;
}
@end
2、给分类添加属性
- 在分类中声明属性,实际上仅仅是声明,并没有实现,实现需要通过 runtime 来完成。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
// 定义关联的key
static const char *key = "name";
@implementation NSObject (Category)
- (NSString *)name {
// 根据关联的 key,获取关联的值。
return objc_getAssociatedObject(self, key);
}
- (void)setName:(NSString *)name {
// 第一个参数:给哪个对象添加关联
// 第二个参数:关联的key,通过这个key获取
// 第三个参数:关联的value
// 第四个参数:关联的策略
objc_setAssociatedObject(self, key, name, OBJC_ASSOCIATION_COPY_NONATOMIC);
}
@end
3、字典转模型 & 归解档实现
- 通过 KVC 实现字典转模型不够灵活,模型的属性和字典的 key 必须一一对应,否则会报错,此时可以用 runtime 灵活的实现
- 实现 NSCoping 协议时,在归档解档方法中获取类的所有属性,再遍历,一个个设置。
1
2
3
4
5
6
7
8
9
// class_copyIvarList:获取类中的所有成员属性(包括定义在 .m 文件中的私有属性)
// 第一个参数:表示获取哪个类中的成员属性
// 第二个参数:表示这个类有多少成员属性,传入一个Int变量地址,会自动给这个变量赋值
unsigned int count;
Ivar *ivarList = class_copyIvarList([self.person class], &count);
// 获取成员属性名
NSString *name = [NSString stringWithUTF8String:ivar_getName(ivarList[i])];
本文由作者按照 CC BY 4.0 进行授权