runtime
说起runtime 只要是oc 开发者都是不陌生的,我们讲到runtime的内容,都是说运行时机制,消息转发啊什么的。
是的 ,runtime理解起来并没有那么的可怕。在这里 ,我就简单的讲讲我对runtime方面的理解。
运行
方法的查找分为三个部分 汇编/C和C++/消息转发
汇编:
1 object_send
1:最开始调用的api 当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。这就是消息传递,我们将在后面详细介绍。
2:很多初学 Objective-C 的人都会把概述中得那句[object doSomething]当成简单的方法调用吧,而忽视了“发送消息”这几个字的深刻含义。其实[object doSomething]应该用[receiver message]来表示,这样的表述更加精确,容易理解,[receiver message]会被编译器转化为:objc_msgSend(receiver, selector),如果消息有参数则转化为objc_msgSend(receiver, selector, arg1, arg2, ...);
2 cachelookup
oc 运行时中用于存储imp的缓存策略。在运行中,查询缓存 ,查询的缓存imp 是存在的,那么 直接调用call imp.(其中要说到cacheHit/cachemiss/以及add)
若查询失败cachemiss,未查找到imp 缓存,那么就发送msg_send_uncache(), 跟到methodtablelookup 去调用C的api(lookupmethodandloadcache3)表示对缓存读取失去信心。此时前往新的方式C,C++的处理方式。
C C++
1:lookUpIMPforward (多次调用) ,realizeClass(实现类),classinitlize(初始化类)
2:方法列表中查找 calss_resolveMethod ----> _class_resoveInstanceMethon (当前类 方法列表的查找)---->_class_resoveClassMethon(父类方法列表查找) 以上都未能查找到方法imp 则进入三次挽回的方法中
消息转发
forwardingTargetForSelector
在oc的中 未能实现以上的查找方式 则我们可以在代码中实现 备用者去转发消息如a 的方法中没有一个walk的方法,但是我们对a 执行[a walk]的房后后,因为未发现这个方法,会造成程序崩溃,但是我们可以在forwardingTargetForSelector 进行备用方法处理,比如 if (Selector == @(walk)) 则return [B new] 返回B对象去接受这个消息。 这样程序就不会早承崩溃。
如果在上一步还不能处理未知消息,则唯一能做的就是启用完整的消息转发机制了。
首先它会发送-methodSignatureForSelector:消息获得函数的参数和返回值类型。如果-methodSignatureForSelector:返回nil,Runtime则会发出-doesNotRecognizeSelector:消息,程序这时也就挂掉了。如果返回了一个函数签名,Runtime就会创建一个NSInvocation对象并发送-forwardInvocation:消息给目标对象。
以上便是JZ对runtime的部分理解,有问题欢迎指正。
网友评论