runtime 可以做什么
这篇文字不扯淡,不讲runtime是什么,只总结下runtime 可以用来干什么。 这几篇文章写的很好: Objective-C Runtime
南大(南锋子)的一系列文章(打开稍慢)
然后饶神总结的也不错,里面好多干货 iOS 基础知识点网址
美团技术团队 深入理解Objective-C:Category 深入理解Objective-C:方法缓存 Obj-C Optimization: IMP Cacheing Deluxe
杨小鱼(玉令天下) Objective-C Runtime
1,获取类属性列表、值、方法
2,替换已有函数(包括系统方法)
可以把系统方法替换为我们自己的方法。
3,动态挂载对象
4,动态创建类 KVO 底层实现原理
5,自动归档、归档解档
[coder encodeObject:value forKey:propertyName];
[self setValue:value forKey:propertyName];
统一为property添加方法 不用一个个的写 demo地址
6,给分类添加属性
7,字典转模型
同样是获取类的属性,然后调用 [instance setValue:value forKey:key]
赋值 demo地址
8, 不会闪退的类 resolveInstanceMethod
使用
在开发中,我们经常会碰到下面这样的错误信息。
-[ForwardingMessageModel test]: unrecognized selector sent to instance 0x60000000c8c0
这是调用了类不存在的方法导致的。
最近我们项目碰到了这样一个问题,因为项目中大量使用了 H5 页面,经常需要原生这边为 H5 提供调用方法,有些方法是后续版本才新加的,之前的版本并不支持,调用了后,就出现了上面的错误,程序直接闪退。
如何保证调用类中不存在的方法时,程序不会闪退呢?
我的做法相当的简单粗暴,在 resolveInstanceMethod
时直接指向一个空方法,上面都不做,具体实现如下:
/*--ForwardingMessageModel.h--*/
#import <Foundation/Foundation.h>
@interface ForwardingMessageModel : NSObject
@end
---
/*--ForwardingMessageModel.m--*/
#import "ForwardingMessageModel.h"
#import <objc/runtime.h>
@implementation ForwardingMessageModel
void rescueCrash (id self,SEL _cmd)
{
NSLog(@"成功的拯救了一次闪退");
}
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
class_addMethod(self, sel, (IMP)rescueCrash, "v:@:");
return YES;
}
- (void)sayHello:(NSString *)name
{
NSLog(@"Hello,%@",name);
}
@end
当再次调用不存在的方法时,动态添加方法,然后直接把方法的 IMP
指向 rescueCrash
的实现:
ForwardingMessageModel *model = [ForwardingMessageModel new];
[model performSelector:@selector(test) withObject:nil];
[model performSelector:@selector(test:) withObject:@"11111"];
[model performSelector:@selector(sayHello:) withObject:@"Yunis"];