runtime 可以做什么

在不断填坑中前进。。

Posted by 三十一 on August 21, 2017

runtime 可以做什么

这篇文字不扯淡,不讲runtime是什么,只总结下runtime 可以用来干什么。 这几篇文章写的很好: Objective-C Runtime

Method Swizzling 和 AOP 实践

南大(南锋子)的一系列文章(打开稍慢)

精通Objective-C进阶技巧:使用运行时系统API

然后饶神总结的也不错,里面好多干货 iOS 基础知识点网址

美团技术团队 深入理解Objective-C:Category 深入理解Objective-C:方法缓存 Obj-C Optimization: IMP Cacheing Deluxe

杨小鱼(玉令天下) Objective-C Runtime

1,获取类属性列表、值、方法

获取model的属性、属性值、方法列表 demo地址

2,替换已有函数(包括系统方法)

可以把系统方法替换为我们自己的方法。

替换系统弹框方法,统一修改弹框标题 demo地址

3,动态挂载对象

为View 加一个小红点的公用方法 demo地址

4,动态创建类 KVO 底层实现原理

KVO的底层实现原理

5,自动归档、归档解档

           

[coder encodeObject:value forKey:propertyName];

[self setValue:value forKey:propertyName];

统一为property添加方法 不用一个个的写 demo地址

6,给分类添加属性

为View 加一个小红点的公用方法 demo地址

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"];