Runtime之objc_msgSend函数
来源:互联网 发布:c4d软件安装教程 编辑:程序博客网 时间:2024/05/29 15:20
首先了解一下什么是Runtime?
Runtime顾名思义即为运行时。就是系统运行时候的一些机制,它提供了一些使得对象之间能够传递消息的重要函数,其中最主要的就是消息机制了。相较于C语言而言,C语言使用的是“静态绑定”,函数的调用在编译期就能知道运行期所需要调用的函数了,编译完成之后就按照顺序执行(面向过程就是这么任性)。而OC使用的是“动态绑定”特性,也就是说编译器在编译期的时候无法决定运行期调用哪个函数,也就是说在编译阶段,OC可以调用任何函数,即使该函数未实现,但只要声明过就不会报错,而C语言则会报错,对象在接收到消息之后,究竟该调用哪个方法完全由运行期决定,甚至可以在程序运行时改变.
1:在对象上调用方法是OC 中经常使用的功能,用 OC 的术语来说,叫做传递消息.消息有名称和选择子,可以接受参数,而且可能有返回值.
2:在 OC 中,如果向某个对象发送消息,那么就会使用动态绑定机制来决定需要调用的方法,在底层所有方法都是c语言函数,然后对象在接收到消息之后,究竟该调用哪个方法则完全于运行期决定,甚至可以在运行时改变,这些特性也使得oc成为了一门真正动态的语言.
3:给对象发送消息可以这样写:
id returnValue = [someObject messageName:parameter];
这个例子中, someObject叫做接受者,messageName叫做选择子,选择子与参数合起来叫做消息.编译器看到此消息之后,将其转换为一条标准的c语言函数,叫做objc_msgSend,其原型为id objc_msgSend(id self, SEL op, …)这是一个参数个数可变的函数,能够接收两个或者两个以上的参数.
第一个参数代表接受者,objc_msgSend第一个参数类型id,它是一个指向类实例的指针.typedef struct objc_object *id;
objc_object原型为:
struct objc_object { Class isa ; };
objc_object结构体包含一个isa指针,根据isa指针就可以找到对象所属的类.
第二个参数代表选择子(SEL是选择子的类型),它是selector在Objc中的表示类型(Swift中是Selector类)。selector是方法选择器,可以理解为区分方法的 ID,而这个 ID 的数据结构是SEL:
typedef struct objc_selector *SEL;
其实它就是个映射到方法的C字符串,你可以用 Objc 编译器命令@selector()或者 Runtime 系统的sel_registerName函数来获得一个SEL类型的方法选择器。
后续参数就是消息中的那些参数,其顺序不变,选择子指的就是方法的名称.
编译器会把刚才那个例子中的消息装换成为如下的函数 :
id returnValue = objc_msgSend(someObject,@selector(messageName:),parameter);
objc_msgSend函数会依据接受者与选择子的类型来调用适当的方法.为了完成此操作,该方法需要在接受者所属的类中搜索其”方法列表”,如果能够找到与选择子名称相符合的方法,就跳转至其实现代码.若是找不到,那就沿着继承体系继续向上査找,等找到了合适的方法之后再调整.如果最终还是找不到相符合的方法,那么就执行”消息转发”.说来,想调用一个方法似乎需要很多步骤.但是幸运的是,objc_msgSend会将匹配的结果缓存到”快速映射表”里面,每个类都有这样一块缓存,若是后面还向该类发送与选择子相同的消息,那么执行起来就很快了.实际一点的例子:
当你写下面这样的代码时
[tableView cellForRowAtIndexPath:indexPath];
编译器实际上把它转换成下面这样的C函数调用
objc_msgSend(tableView, @selector(cellForRowAtIndexPath:), indexPath);
5:下面理解一下其他几个函数:
objc_msgSend_stret():如果待发送的消息要返回结构体,那么交给此函数处理.只有当CPU的寄存器能够容纳得下消息返回类型时,这个函数才能够处理此消息.若是无法容纳于 CPU 寄存器中,那么就由另一个函数执行派发.此时,那个函数会通过分配在栈上的某个变量来处理消息所返回的结构体.
objc_msgSend_fpret():如果消息返回的是浮点数,那么可由此函数来处理,在某些架构的 CPU 中调用函数时,需要对”浮点数寄存器”做特殊处理.
objc_msgSendSuper():如果要对超类发送消息,那么就要交给此函数处理.也有与objc_msgSend_stret(),objc_msgSend_fpret()两个等效的函数用于处理超类的相应消息.
推荐播客:
http://www.cocoachina.com/ios/20150812/12992.html
- Runtime之objc_msgSend函数
- Objective-C Runtime 【objc_msgSend函数】
- runtime objc_msgSend
- runtime-objc_msgSend
- runtime简单理解之消息传递 objc_msgSend
- Xcode6调试runtime机制的objc_msgSend函数时报错
- runtime简单学习之消息传递objc_msgSend(二)
- runtime-class_addMethod\objc_msgSend\NSInvocation
- iOS笔记-runtime objc_msgSend
- runtime objc_msgSend消息发送
- objc_msgSend函数
- objc_msgSend函数
- objc_msgSend函数 iphone
- objc_msgSend函数 iphone
- ios objc_msgSend函数
- iOS objc_msgSend函数
- Objective-C Runtime分析(三)-objc_msgSend
- IOS -- objc_msgSend 函数的理解
- C#Timer 控件
- 反射
- Android 录音声波图
- 欢迎使用CSDN-markdown编辑器
- Spring项目中使用Junit单元测试并配置数据源的问题
- Runtime之objc_msgSend函数
- POJ 2393 Yogurt factory(贪心)
- fastdfs上传文件只有文件服务器上该文件同路径下多一个-m的文件
- Cannot load library: soinfo_link_image(linker.cpp:1635)
- socket select模型
- 记一次现场SDE无法启动的解决
- ios 收起键盘
- TableView性能优化——动态cell适应工具(UITableView+FDTemplateLayoutCell)
- Java反射