iOS开发知识

从RunTime源码回看消息发送及其基础知识

2019-07-30  本文已影响0人  太阳骑士索拉尔

关于我的仓库

前言

准备工作

method_t

///class_rw_t
// 方法信息
method_array_t methods;

///method_array_t
list_array_tt<method_t, method_list_t>
  
///method_t
struct method_t {
    SEL name;
    const char *types;  //方法标签
    MethodListIMP imp;
};

SEL name

///Person.m
#import "Person.h"
@implementation Person

- (void)eat {
    NSLog(@"Person EAT");
}

- (void)eat:(NSString *)str {
    NSLog(@"Person EATSTR");
}

- (void)dayin {
    NSLog(@"dayin");
    SEL sell1 = @selector(eat:);
    NSLog(@"sell1:%p", sell1);
    SEL sell2 = @selector(eat);
    NSLog(@"sell2:%p", sell2);
}

@end

///main.m
#import <Foundation/Foundation.h>
#include "Student.h"
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        Person *newPerson = [[Person alloc] init];
        [newPerson dayin];
    }
    return 0;
}

///结果
//dayin
//sell1:0x100000f63
//sell2:0x100000f68
28653839_1361282379yvAk

const char *types

QQ20190729-194442
char *buf1 = @encode(int **);
char *buf2 = @encode(struct key);
char *buf3 = @encode(Rectangle);

MethodListIMP imp

方法调用的大致流程【消息发送】

- (void)test:(NSInteger)num {
    NSLog(@"You know nothing about power!");
}

[person test:12];

//这短短一句话传递了,三个信息
//调用者:person
//方法名:test:
//参数:12
//这样一句话就会被转换为objc_msgSend(self, @selector(test:), 12);

imp具体作用

- (void)dayin {
    NSLog(@"dayin");
    SEL sell1 = @selector(eat);
    NSLog(@"sell1:%p", sell1);
    IMP imp1 = [self methodForSelector:sell1];  //根据sel获取imp
    NSLog(@"imp1:%p", imp1);
    SEL sell2 = @selector(eat:);
    NSLog(@"sell2:%p", sell2);
    IMP imp2 = [self methodForSelector:sell2];
    NSLog(@"imp2:%p", imp2);
    SEL sell3 = @selector(drink:);
    NSLog(@"sell3:%p", sell3);
    IMP imp3 = [self methodForSelector:sell3];
    NSLog(@"imp3:%p", imp3);
  
    imp1();//可以像这样直接调用imp函数,如果要加参数的话,直接在methodForSelector中加
}

//sell1:0x100000f51
//imp1:0x100000be0
//sell2:0x100000f68
//imp2:0x7fff7c89c300
//sell3:0x100000f6d
//imp3:0x7fff7c89c300

在cache以及rw结构体中方法存储的区别

//bucket_t
struct bucket_t {
    cache_key_t _key;
    //sel
    MethodCacheIMP _imp;
    //函数内存地址
}

//method_t
struct method_t {
    SEL name;
    const char *types;
    MethodListIMP imp;
};
上一篇 下一篇

猜你喜欢

热点阅读