Runtime 常用场景(四)

1. Runtime 怎么添加属性、方法?

* ivar 表示成员变量
* class_addIvar
* class_addMethod
* class_addProperty
* class_addProtocol
* class_replacePropeerty

2.Runtime 如何实现 weak 属性?

weak 策略表明该属性定义了一种“非拥有关系”(nonowning reelationship)。为这种属性设置新值时,设置方法既不保留新值,也不是放旧值。此特质和assign 雷西;然而在属性所指的对象遭到毁灭时,属性值也饿会清空(nil out)。

那么 runtime 如何实现 weak 变量自动置 nil?

runtime 对注册的类会进行布局,将 weak 对象放入一个 hash 表中。用weak 指向的对象内存地址是a,那么就会以a 为key,在这个 weak hash 表中搜索,找到所有以 a 为 key 的weak 对象,从而设置为 nil。

weak 属性需要在dealloc 中设置nil 么
在 ARC 环境中无论是强指针还是弱指针都无需在 dealloc 设置nil, ARC 会自动帮我们处理
即便是编译器不帮我们做这些事情, weak 也不需要在 dealloc 中置 nil, 在属性所致对象操刀摧毁时,属性值也会清空!

3.runtime 如何通过 selector 找到对应的 IMP 地址?(分别考虑类方法和实例方法)

1.每一个类对象中都一个对象方法列表(对象方法缓存)
2.类方法列表是存放在类对象中 isa 指针指向的元类对象中(类方法缓存)
3.方法列表中每个方法结构体中记录着方法的名称,方法实现以及参数类型
4.方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现
5.当我们发送一个消息给一个NSObject 对象时,这条消息会在对象的类方法列表中查找
6.当我们发送一个消息给一个类时,这条消息会在类的 Meta Class 对象的方法列表中查找

4.使用runtime Associate 方法关联的对象,需要在主对象dealloc 的时候释放吗?

无论在MRC下还是ARC下均不需要被关联的对象在生命周期内要比对象本身释放的晚很多,他们会在被 NSObject-dealloc 调用的 object_dispose()方法中释放

补充:对象的内存销毁时间表,分为四个步骤

1、调用 -release: 引用计数变为零
* 对象正在被销毁,生命周期即将结束。
* 不能再有新的 _weak 若饮用,否则将指向nil.
* 调用 [self dealloc]

2、父类调用-dealloc
* 继承关系中最直接继承的父类在调用 -dealloc
* 如果是 MRC 代码,则会手动释放实例变量们(Ivars)
* 继承关系中每一层的父类,都在调用 -dealloc

3、NSObject 调用 -dealloc
* 只做一件事:调用Objective-C runtime 中的object_dispose() 方法

4、调用objetc_dispose() 
* 为 C++ 的实例变量们(Ivars)调用destructors
* 为 ARC 状态下的实例变量们(Ivars)调用 -release
* 解除所有使用 runtime Associate 方法关联的对象
* 调用所有 _weak 饮用
* 调用 free()

5. _objc_msgForward 函数是做什么的?直接调用它将会发生什么?

_objc_msgForward 是 IMP 类型,用于消息转发:当向一个对象发送一条消息,他并没有实现的时候,_objc_msgForward 会尝试做消息转发
直接调用 _objc_msgForward 会非常危险的事情,这是一把双刃剑,用得好,会做很多非常酷的事情,但是用不好,会直接导致程序Creash.

6.能否向编译后得到的类中增加实例变量?能否向运行时创建的类中增加实例变量?为什么?

不能想编译后的得到的类中增加实例变量;
能向运行时创建的类中添加实例变量;
原因如下:
1.因为编译后的类已经注册在runtime 中,类结构体中的 objc_ivar_list 实例变量的链表和instance_size 实例变量的内存大小已经确定,同时 runtime 会调用class_setIvarLayout 或 class_setWeakIvarLayout 来处理 strong weak 引用,所以不能向存在的类中添加实例变量
2.运行时创建的类是可以添加实例变量,调用class_addIcar 函数,但是得在调用 objc_allocateClassPair之后,objc_registerClassPair之后

7.简述OC 中调用方法的过程(runtime)

OC 是动态语言,每个方法在运行时都会被动态转为消息发送,即: objc_msgSend(seceiver,selector),整体过程如下:
1.objc. 在给一个对象发送消息时,runtime 库会根据对象的 isa 指针找到该对象实际所属的类
2.然后在该类中的方法列表一机其父类方法列表中寻找方法运行
3.如果,在最顶层的额父类(一般也就是NSObject )中依然找不到对应的方法时,程序在运行时会挂掉并抛出异常 unrecongnized selector send to XXX
但是在这之前,objc 的运行时会给出三次机会拯救程序崩溃的机会

补充说明:Runtime 铸就了OC 的动态语言的特性,使得C语言具备了面向对象的特性,在程序运行期间创建,检查,修改类、对象以及其对应的方法,这些操作都可以使用 runtime 中的对应方法实现。

8.什么是method swizzing?

* 简单的说就是进行方法交换
* 在OC中调用一个方法,其实就是给一个对象发送消息,查找消息唯一一句就是selector 名字。利用OC 的动态特性,可以实现在运行时偷换 selector 对应的方法实现,达到给方法挂钩的目的
* 每个类都有一个方法列表,存放着方法的名字和方法实现的映射关系,selector 的本质就是方法名, IMP 有点类似函数指针,指向具体的 Method 实现,通过 selector 找到对应的 IMP。

* 方法交换的几种方式
           <1>. 利用 method_exchangeImplementations 交换两个方法的实现
           <2>. 利用 class_replaceMethod 替换方法的实现
           <3>.利用 method_setImplementation 来设置某个方法的 IMP

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值