美文网首页
runtime笔记(为了防止自己忘记,不断更新)

runtime笔记(为了防止自己忘记,不断更新)

作者: 扶摇先生 | 来源:发表于2018-04-02 10:50 被阅读2次

1、 是什么(what)
runtime是属于OC的底层,是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API,可以进行一些非常底层的操作(用OC是无法现实的, 不好实现)。 在我们平时编写的OC代码中, 程序运行过程时, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者。
2、用途(purpose)
1)为类动态添加新的方法
首先如果要执行一个类里边没有的方法,可以调用+(BOOL)resolveInstanceMethod 这个方法,然后再在这个类里重写这个方法的实现,然后在里边调用class_addMethod,然后添加你想添加的方法,用来实现一些功能,从而使代码更加模块化,解耦连。具体代码如下

#import <Foundation/Foundation.h>
// .h文件
@interface Cat : NSObject

@end

#import "Cat.h"
#import <objc/message.h>//.m文件
@implementation Cat

void tangtang_eat(id self, SEL _cmd) {// 自定义的eat方法。
    NSLog(@"执行eat方法,%@ %@",self,NSStringFromSelector(_cmd));
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(eat)) {
        class_addMethod(self, sel, (IMP)tangtang_eat, "我要吃糖糖");
        return YES;
    }
        return  [super resolveInstanceMethod:sel];
}
@end

控制器里调用

Cat *cat = [[Cat alloc] init];
    [cat performSelector:@selector(eat) withObject:nil];

log如下

2018-04-02 10:20:38.654264+0800 newApplicationNetWork[4180:1868414] 执行eat方法,<Cat: 0x60400000fa50> eat

以上是动态添加不带参数的方法,当然,我也可以添加带参数的。代码和log如下(自己看区别)

#import <Foundation/Foundation.h>
// .h文件
@interface Cat : NSObject

@end

#import "Cat.h"
#import <objc/message.h>//.m文件
@implementation Cat

void tangtang_bark(id self, SEL _cmd, id para) {
    NSLog(@"执行bark 方法,  %@, %@, %@",self, NSStringFromSelector(_cmd), para);
}
+ (BOOL)resolveInstanceMethod:(SEL)sel {
    if (sel == @selector(bark)) {
      class_addMethod(self, sel, (IMP)tangtang_bark, "我要叫妞妞");
        return YES;
    }
        return  [super resolveInstanceMethod:sel];
}
@end
Cat *cat = [[Cat alloc] init];
    [cat performSelector:@selector(bark) withObject:@{@"key":@"value"}];

log

2018-04-02 10:20:40.768356+0800 newApplicationNetWork[4180:1868414] 执行bark 方法,  <Cat: 0x600000005130>, bark, {
    key = value;
}

2)关于objc_msgSend
关于objc_msgSend调用的四种写法

id (*sendMessage)(id, SEL, id, id, id) = (id (*)(id, SEL, id, id, id))objc_msgSend;
float (*sendFloatMessage)(id, SEL, id, id, id) = (float (*)(id, SEL, id, id, id))objc_msgSend;
BOOL (*sendBOOLMessage)(id, SEL, id, id, id) = (BOOL (*)(id, SEL, id, id, id))objc_msgSend;
void (*sendVoidMessage)(id, SEL, id, id, id) = (void (*)(id, SEL, id, id, id))objc_msgSend;

我们以void (sendVoidMessage)(id, SEL, id, id, id) = (void ()(id, SEL, id, id, id))objc_msgSend为例写一段代码
首先我们创建一个Dog类

#import <Foundation/Foundation.h>

@interface Dog : NSObject
@property(nonatomic, strong) NSString * dogName;
@property(nonatomic, assign) NSInteger dogAge;

@end
#import "Dog.h"

@interface Dog ()

@property(nonatomic, strong) NSString * dogSex;

@end

@implementation Dog

- (instancetype)init
{
    self = [super init];
    if (self) {
        self.dogName = @"dahuang";
        self.dogAge = 2;
        NSLog(@"实例化");
    }
    return self;
}
- (void)setDogAge:(NSInteger)dogAge {
    NSLog(@"dogAge --- %ld",dogAge);
}
- (void)setDogName:(NSString *)dogName {
    NSLog(@"dogName --- %@",dogName);
}
- (void)printDogName
{
    NSLog(@"dogName");
}
- (void)eatFruit {
    NSLog(@"eatFruit");
}
@end

控制器里导入和runtime相关的类以及Dog类

#import "Dog.h"
#import <objc/runtime.h>
#import <objc/message.h>

我们要通过objc_msgSend来执行eatFruit,代码如下:

    Dog *dog = [[Dog alloc] init];
SEL methodSEL = NSSelectorFromString(@"eatFruit");
    if (methodSEL == @selector(eatFruit)) {
        ((void(*)(id, SEL ,id , id)) objc_msgSend)(dog, methodSEL, nil,nil);
    }

其他的方法和这个方法一样,自己类比举一反三就好了
在使用runtime时一定不要忘记释放对象,要不然会引起内存泄露

  1. class_copyPropertyList与class_copyIvarList区别
    class_copyPropertyList返回的仅仅是对象类的属性(@property申明的属性),而class_copyIvarList返回类的所有属性和变量(包括在@interface大括号中声明的变量)
    先更新这些,以后会不断更新。

相关文章

  • runtime笔记(为了防止自己忘记,不断更新)

    1、 是什么(what)runtime是属于OC的底层,是一套比较底层的纯C语言API, 属于1个C语言库, 包含...

  • 分布式服务框架

    本文是我自己将来面试的笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那就点个小...

  • SpringCloud概述

    本文是我自己将来面试的笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那就点个小...

  • SpringCloud_Eureka

    本文是我自己将来面试的笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那就点个小...

  • 基础-JAVA基础

    本文是我自己将来面试的笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那就点个小...

  • JPush 使用教程

    自己使用的一些经验,为了方便直接从这里复制过去就行。就当做个笔记,防止长时间忘记之后,还需要去官网看文档。 主要思...

  • 01 ---- Python 基本数字类型及其操作、

    前几天学了Python的基本数据类型,趁现在还没忘记所以就来做做笔记。防止以后自己忘记咯~~ 数字类型-- 对我印...

  • MySQL数据库——面试知识点整理

    本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...

  • Redis——面试知识点总结

    本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...

  • Java知识——基础知识

    本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...

网友评论

      本文标题:runtime笔记(为了防止自己忘记,不断更新)

      本文链接:https://www.haomeiwen.com/subject/aoethftx.html