iOS 运行时 Runtime 运用解析

在 iOS 开发中,我们可能会使用 Runtime 来解决问题,当然我们可能都接触过 Runtime,有的小伙伴已经很熟悉了,有的小伙伴也可能不是特别清楚,为了让小伙伴们更好地使用 Runtime,我对 Runtime 做了一个小小的封装,先看一下效果吧。

Runtime 运用

使用说明

  • 导入头文件
#import "DYFRuntimeWrapper.h"
  • Runtime 应用介绍
  1. 获取所有方法名,例如获取 UITableView 的方法名:
NSArray *list = [DYFRuntimeWrapper yf_getAllMethodsWithClass:[UITableView class]];

for (NSString *name in list) {
    NSLog(@">>>> %@", name);
}
  1. 获取所有属性名,例如获取 UILabel 的属性变量:
NSArray *list = [DYFRuntimeWrapper yf_getAllIvarsWithClass:[UILabel class]];

for (NSString *name in list) {
    NSLog(@">>>> %@", name);
}
  1. 添加一个方法
+ (void)load {
    [DYFRuntimeWrapper yf_addMethodWithClass:[self class] methodName:@"hello" impClass:[self class] impName:@"sayHello"];
}

- (void)viewDidLoad {
    [super viewDidLoad];

#pragma clang diagnostic push
#pragma clang diagnostic ignored "-Warc-performSelector-leaks"
    [self performSelector:NSSelectorFromString(@"hello")];
#pragma clang diagnostic pop
}

- (void)sayHello {
    NSLog(@">>>> %s", __FUNCTION__);
}
  1. 交换两个方法
- (IBAction)exchangeMethod:(id)sender {
    [DYFRuntimeWrapper yf_exchangeMethodWithSourceClass:[self class] sourceSel:@selector(preload) targetClass:[self class] targetSel:@selector(refreshUI)];
}

- (void)preload {
    NSString *str = [NSString stringWithFormat:@"%s\n", __FUNCTION__];
    NSLog(@">>>> str1: %@", str);
    self.displayView.text = [self.displayView.text stringByAppendingString:str];
    NSLog(@">>>> self.displayView.text: %@", self.displayView.text);
}

- (void)refreshUI {
    NSString *str = [NSString stringWithFormat:@"%s-%@\n", __FUNCTION__, self.randomString];
    NSLog(@">>>> str2: %@", str);
    self.displayView.text = [self.displayView.text stringByAppendingString:str];
    NSLog(@">>>> self.displayView.text: %@", self.displayView.text);
}

- (NSString *)randomString {
    uint32_t a = arc4random_uniform(2);
    unsigned int len = (a == 1) ? 40 : 32;
    char data[len];
    for (int x = 0; x < len; x++) {
        uint32_t ar = arc4random_uniform(2);
        char ch = (char)(((ar == 1) ? 'A' : 'a') + (arc4random_uniform(26)));
        data[x] = ch;
    }
    return [[NSString alloc] initWithBytes:data length:len encoding:NSUTF8StringEncoding];
}
  1. 替换某个方法
- (IBAction)replaceMethod:(id)sender {
    [DYFRuntimeWrapper yf_replaceMethodWithSourceClass:[self class] sourceSel:@selector(preload) targetClass:[self class] targetSel:@selector(refreshUI)];
}
// 同上
  1. 字典转模型
- (IBAction)dictToModel:(id)sender {
    NSDictionary *dict = @{@"name": self.nameTF.text,
                           @"gender": self.genderTF.text,
                           @"age": self.ageTF.text};
    YFModel *model = [DYFRuntimeWrapper yf_modelWithDict:dict modelClass:[YFModel class]];
    self.displayView.text = [self.displayView.text stringByAppendingString:[NSString stringWithFormat:@"\nname: %@\ngender: %@\nage: %@", model.name, model.gender, model.age]];
}
  1. 归档解档
- (void)viewDidLoad {
    [super viewDidLoad];
    // 创建路径
    NSString *documentPath      = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES) lastObject];
    NSString *filePath          = [documentPath stringByAppendingPathComponent:@"YFModel.plist"];
    self.filePath               = filePath;
}

- (IBAction)archive:(id)sender {
    YFModel *model = [YFModel new];
    model.name     = self.nameTF.text;
    model.gender   = self.genderTF.text;
    model.age      = self.ageTF.text;
    
    BOOL ret = [DYFRuntimeWrapper yf_archive:[model class] model:model filePath:self.filePath];
    if (ret) {
        NSLog(@">>>> 归档成功:%@", self.filePath);
    } else {
        NSLog(@">>>> 归档失败!!!");
    }
}

- (IBAction)unarchive:(id)sender {
    self.displayView.text = @"解档后的数据:";
    
    YFModel *m = [DYFRuntimeWrapper yf_unarchive:[YFModel class] filePath:self.filePath];
    
    self.displayView.text = [self.displayView.text stringByAppendingString:[NSString stringWithFormat:@"\nname: %@\ngender: %@\nage: %@", m.name, m.gender, m.age]];
}
  1. 添加分类属性
  • 导入头文件#import <objc/message.h>

  • 声明属性

/** 居住地址 */
@property (nonatomic, copy) NSString *address;
  • 申明一个key值
static NSString *kHomeAddress = @"kHomeAddress";
  • 重写setter、getter方法
 // getter
- (NSString *)address {
    return objc_getAssociatedObject(self, &kHomeAddress);
}

// setter
- (void)setAddress:(NSString *)address {
    objc_setAssociatedObject(self, &kHomeAddress, address, OBJC_ASSOCIATION_COPY_NONATOMIC);
}

这样就成功添加了一个分类属性

Runtime 应用的封装主要实现都在 DYFRuntimeWrapper 类中,如果需要快速使用 Runtime,就去查看或下载 Demo。


点赞+关注,第一时间获取技术干货和最新知识点,谢谢你的支持!

最后祝大家生活愉快~

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,796评论 1 32
  • 传奇影业怪兽电影宇宙第三篇 《哥斯拉2:怪物之王》2019.5.31 承接2014年《哥斯拉》“帝王计划”组织发现...
    夏洛克不养猫阅读 4,878评论 0 4
  • 这是我最近看的育儿书,真是有了孩子以后,我真怕教不好她,因为不想因为自己的想当然就所以然的教孩子,我现在就深切的感...
    静静_ee7f阅读 1,885评论 0 1
  • 2019年4月24日 星期三 晴 今天你学钢琴的地方搞了一个练习指法的活动,六点钟开始,我们要放了学赶紧回家吃饭,...
    刘芮希爸爸阅读 1,261评论 0 0
  • 2 有了第一次的经历,我对相亲不那么排斥了。其实相亲就是通过介绍相互认识一下,觉得可以就加个微信聊一聊,离结婚还远...
    枫丹白露Town阅读 1,358评论 0 2