推广

RunTime

iseeyu2年前 (2024-02-21)推广179

Cache_t.png

class_data_bits_t bits

class_data_bits_t主要是对class_rw_t的封装
class_rw_t代表了类相关的读写信息、对class_ro_t的封装

class_data_bits_t bits 组成
  • class_rw_t
    ① class_ro_t 代表了类相关的只读信息
    ② protocols
    ③ properties
    ④ methods

    class_rw_t.png

  • class_ro_t

    Class_ro_t.png

  • isa指针
    ① 指针型isa 的值代表Class的地址
    ② 非指针型isa 的值的部分代表Class的地址
    ③ 产生这两种的初衷:我们在寻址实际上30~40位数就可以保证我们寻找到所有class的地址,多出来的位可以存储一些别的内容,来达到节省内存的目的
    ④ 指向题:

    1. 关于对象,其指向类对象
    2. 关于类对象,其指向元类对象
    3. 如果是实例方法从类对象查找,如果是类方法从元类对象查找

      isa指针.png

method_t

method_t.png

  • SEL name:方法的名称
  • const char *types:函数返回值和参数的组合
  • IMP imp:无类型的函数指针

type Encodings技术

Type Encoding.png

  • 使method指向了函数体的返回值,参数等
  • 返回值占据第一位,返回值只有一个或者没有

    20210622-155020.png

数据结构总结

Runtime数据结构.png

对象、类对象、元类对象

  • 类对象存储实例方法列表等信息
  • 元类对象存储类方法类表等信息
  • 类对象和元类对象都是objc_class数据结构,由于继承了objc_object数据结构所以才有isa指针,
  • 所以才能实例对象找到类对象访问它的实例方法列表等信息,
  • 类对象通过isa可以找到元类对象访问类方法列表等信息
  • 元类对象的isa指针(包含根元类对象)都指向根元类对象
  • 根元类对象的superclass指向的根类对象
    注:当在根类中的类方法没找到,会指向根类对象中去查找它的同名的实例方法

消息传递过程

实例方法消息传递过程

1、 调用了一个实例对象A对象的实例方法
2、 通过A实例对象的isa指针找到它的类对象,类对象中遍历方法列表去查找同名的方法实现,找到后Runtime发送消息调用
3、 如果没有找到就会根据superclass指针指向的父类对象,并查找其方法列表。。。直到根类对象中的方法列表,如果找到Runtime发送消息调用,如果到根类对象还没有找到就会返回nil

类方的消息传递过程

1、 调用一个类对象的类方法。
2、 通过类对象的isa指针找到元类对象,元类对象中遍历方法列表查找同名的类方法实现,找到后直接调用
3、如果没有找到就会通过superclass指针指向父元类对象,并查找其类方法列表。。。直到根元类对象中的类方法列表,如果找到直接调用,如果没有找到进入到消息转发
4、根元类对象如果没有找到会superclass会指向根类对象,并查找同名的实例方法,如果找到直接调用,如果没有找到返回nil

消息传递

消息传递.png

消息传递Supr.png

消息传递流程.png

1、缓存查找

例: 给定值是SEL 目标值是对应bucket_t的IMP。

  • 首先给定的函数选择器通过一个函数来映射出bucket_t在数组当中位置,这个过程是hash查找
  • 哈希查找实际上,通过给定的一个值比如说方法的选择器经过哈希函数的算法酸楚的值实际上就是给定值在对应数组当中所对应的索引位置。
    ① f(key) = key & mask
    ② 通过哈希查 解决查找效率的问题
    ③ 通过哈希查找,找到对应的bucket_t,就可以拿到IMP

2、当前类中查找

对于已排序好的列表,采用二分查找算法查找方法对应执行函数
对于没有排序的列表,采用一般遍历查找方法对应执行函数

3、父类逐级查找

父类逐级查找的过程.png

消息转发

消息转发.png

Method-Swizzling

MethodSwizzling.png

Method method1 = class_getInstanceMethod(self, @selector(test));
Method method2 = class_getInstanceMethod(self, @selector(Mytest));
method_exchangeImplementations(method1, method2);

使用场景

替换系统的viewdidLoad或者viewwillDismiss中,在替换的方法中,添加我们自己的代码,例如添加时长统计,来统计进入当前界面的时长

动态添加方法

编译的时候没有这个方法,运行时有这个方法需要调用performSelector方法,在消息转发中的第一次处理函数resolveInstanceMethod动态添加DoThings:Num:方法

+ (BOOL)resolveInstanceMethod:(SEL)sel{

    NSLog(@"%@",NSStringFromSelector(sel));

    if(sel == @selector(DoThings:Num:)){
        class_addMethod([self class], sel, (IMP)MyMethodIMP, "v@:");
        return YES;
    }

    return  [super resolveInstanceMethod:sel];
}

void MyMethodIMP(id self,SEL _cmd,NSString * name,NSInteger num){
    
    NSLog(@"调用了消息转发的内容");
    NSLog(@"%@",NSStringFromSelector(_cmd));
    NSLog(@"%@",name);
    NSLog(@"%ld",(long)num);
}

动态添加调用的函数

class_addMethod([self class], sel, (IMP)MyMethodIMP, "v@:");

动态添加函数参数说明

20210622-161516.png

动态方法解析

@dynamic

-动态运行时语言将函数决议推迟到运行时。
① 当我们把一个属性标示为@dynamic的时候代表着不需要编译器在编译时,为我们生成属性的setter跟getter方法的具体实现,而在在具体运行时我们调用了setter、geter方法的时候,再去添加具体的实现。
② 这种功能也只有动态运行时特性的语言支持

  • 编译时语言在编译期进行函数决议

MST

nsobject有父类吗?

没有nsobject是根类

当在跟类中的类方法没找到,但是有同名的实例方法实现,那么会不会崩溃?会不会产生实际的调用?

由于根元类对象的superclass指针指向了根类对象,去查找实例同名的实例方法,如果找到就会执行同名的实例方法调用

下图中打印的是什么?

笔试题1.png

[self class]会转化成     
objc_msgSend(<#id  _Nullable self#>, <#SEL  _Nonnull op, ...#>)
phone的实例对象,[self class],通过isa找到phone类对象,phone类对象是没有class的,通过superclass找到父类的。。。直到查找到根类nsobject,有calss的实现,打印出来的自然是phone

[super class]会转化成
objc_msgSendSuper(<#struct objc_super * _Nonnull super#>, <#SEL  _Nonnull op, ...#>)

objc_msgSendSuper实际的接收者仍然是phone的这个实例对象,objc_msgSendSuper传递的含义,从phone的这个实例对象的父类开始查找,  直到查找到根类nsobject有class的实现,所以打印出来的结果还是phone

打印结果都是phone

对页面的进出添加进出信息

使用MethodSwizzling来交换viewDidLoad和viewWillAppear,在替换代码中添加一些埋点操作

[obj foo]和objc_msgSend()函数之间有什么关系?

  • 向 obj对象发送一条foo的消息,[obj foo]在编译期处理以后就变成了objc_msgSend(obj,@selector(foo))
  • 由于没有参数,所以 objc_msgSend函数调用只有2个参数
  • 然后就开始了runtime的消息传递过程

runtime如何通过Selector找到对应的IMP地址的?

  • 查找当前实例所对应类对象的缓存,是否有selelctor对应imp实现如果缓存命中了,我们就把命中的缓存函数返回给调用方。
  • 如果缓存没有就去当前类的方法列表查找selector对应的imp实现
  • 当前类如果没有命中,就根据当前类的superclass逐级查找父类的方法列表。。。直到根类对象,直到查到selector方法的imp实现

能否向编译后的类中增加实例变量?

class_ro_t ro代表的是readonly
编译后的类是无法添加实例变量的。

能否向动态添加的类中增加实例变量?

可以的,动态添加的这个类过程当中只要在它调用注册方法之前去完成实例变量的添加就是可以实现的

isa指针的含义?

  • 非指针类型 isa值的部分代表calss地址
  • 指针类型isa 代表class地址

扫描二维码推送至手机访问。

版权声明:本文由西安泽虎代运营发布,如需转载请注明出处。

转载请注明出处https://www.0291.com.cn/post/56868.html

相关文章

小编教你家电维修百度推广,家电维修免费推广网站。

小编教你家电维修百度推广,家电维修免费推广网站。

网络推广是所有商家推广产品面临的首要问题。要知道如何推广网络,首先要知道什么是网络推广。通过互联网直接或间接推广品牌或产品可以称为网络推广,也可以称为网络营销。众所周知,二战期间,美军巴顿将军非常擅长运用装甲战术,赢得了多场战役。先进的战术对战争中的胜利非常有效。在现代商场战争中,网络推广就像二战中...

软文有哪些推广渠道?怎么巧妙的植入公司品牌信息

软文有哪些推广渠道?怎么巧妙的植入公司品牌信息

软文有哪些?怎么巧妙的植入公司信息?如何写新闻稿的标题,如何成为一个好的标题?这里的好是从媒体的角度来看的。从媒体的角度来看,标题应该清晰易懂,简短有力,标题应该接近趋势,新趋势,以吸引注意力。就企业新闻稿而言,写一个好的标题是吸引读者和媒体的第一步,也是最基本的一步。如何...

什么是淘宝子账号(淘宝的子账号是什么)

什么是淘宝子账号(淘宝的子账号是什么)

淘宝平台有好多账号,每个商家都会注册一个商家账号的,但是有些商家不只有一个账号,还会有子账号。淘宝子账号子账号也称之为员工管理,子账号相当于帐号的其他管理员。淘宝子账号有沟通功能(与人聊天、旺旺分流接单)、店铺管理(需得到主账号授权)。...

淘宝联盟推广扣税吗,淘宝联盟佣金怎么算的(淘宝联盟扣税和技术服务费)

淘宝联盟推广扣税吗,淘宝联盟佣金怎么算的(淘宝联盟扣税和技术服务费)

淘宝联盟频道推广最丰富的强势类目,精选最优质的卖家和商品,提供最新的促销活动,达到最大买家覆盖范围,为买家带来全新的一站式购物体验。...

营销过度是营销型网站的禁忌。

营销过度是营销型网站的禁忌。

现在,只要我们提到网站的建设,很多人都会联想到营销网站的建设,但是什么是营销网站,很多人没有一个具体的概念。从优化猩网站建设和研究技术来看,营销网站的核心是用户体验高的网站。目前,很多企业的网站都很精致,内容丰富,但用户体验差,这样的网站,无论怎样做营销,都不能称为真正的营销网站。正因为如此,许多...

我来教你SEO排名降低的核查方式有哪些。

我来教你SEO排名降低的核查方式有哪些。

在SEO工作上,我们有时候会遭受,沒有任何原因,排名便开始降低,乃至消退,应对这一难题,许多工作员会第一时间觉得,它将会是百度搜索计算方法在调节。而依据过去的SEO实战演练实例,我们发觉:造成搜索引擎排名降低的缘故,并不是是实在太繁杂的计算方法,或许就是说平时工作上的1个小关键点。那么,SEO排名降...

现在,非常期待与您的又一次邂逅

我们努力让每一部企业宣传片和抖音短视频成为商业大片