IOS -执行时 (消息传递 )
一 函数调用概述
Objective-C不支持多重继承(同Java和Smalltalk),而C++语言支持多重继承。
Objective-C是动态绑定,它的类库比C++要easy操作。
Objective-C在执行时能够同意依据字符串名字来訪问方法和类。还能够动态连接和加入类。 C++ 跟从面向对象编程里的Simula 67(一种早期OO语言)学派,而Objecive-C属于Smalltalk学派。Simula 67学派更安全。由于大部分错误能够在编译时查出。
在C++里,对象的静态类型决定你能否够发送消息给它,而对Objective-C来说。由动态类型来决定。
Objective-C比C++ 更强调类型的动态性,尽管牺牲了一些运行性能。但因为模型清晰,而牺牲的这些性能能够在今天由更先进的编译技术来弥补。
二 消息的产生
在Objective-c中消息一直到执行时才干绑定到相应的函数:
[reveiver message];
编译器在处理时会将上面的表达式处理称以下这样的形式:
objc_msgSend(receiver,selector);
假设方法有多个參数的时候会处理成以下这样的形式:
objc_msgSend(receiver,selector,arg1,arg2。…….);
如今我们知道了在Objective-c中函数调用都会被编译器进行预处理,调用obj_msgSend函数进行消息的发送。 这里须要弄明确的selector是什么东东?receiver是怎么样来调用指定的函数的,它在背后是如何实现的?以下将逐一解释。
三 类对象中与消息有关的结构
首先看一下与消息传递有关的几个数据结构和数据类型。
1. struct objc_method_list **methodLists
在上一节中知道在类对象objc_class中有一个结构体 struct objc_method_list **methodLists ,它事实上是方法的映射表。
struct objc_method_list {
struct objc_method_list *obsolete
int method_count
struct objc_method method_list[1]
}
在objc_method_list中包括一个objc_method结构体
struct objc_method {
SEL method_name
char *method_types
IMP method_imp
}
IMP - 指向该方法的详细实现的函数指针。
对于每一个參数以下将详细说明。
opaque type that represents a method selector)
一个用来区分这种方法唯一的ID,这个ID就是 SEL类型的。
(A
selector is the name used to select a method to execute for an object, or the unique identifier that replaces the name when the source code is compiled. A selector by itself doesn’t do anything. It simply identifies a method. The only thing that makes the
selector method name different from a plain string is that the compiler makes sure that selectors are unique. )仅仅要方法的名字(包含參数序列)同样,那么它们的 ID都是同样的。
就是
说,无论是超类还是子类,无论是有没有超类和子类的关系,仅仅要名字同样那么ID就是一样的。
是不支持在类内函数重载的),那如何进行区分呢?请继续往下看。
( A pointer to the function of a method implementation)
...)
- (void) viewDidLoad
{
[super viewDidLoad];
//声明一个函数指针
void (*MyPrint)(id,SEL,NSString*);
MyPrint = ( void (*)(id,SEL,NSString*) )[self methodForSelector:@selector(Print:)];
MyPrint(self,@selector(Print:),@"Hello World");
} - (void) Print:(NSString*) str
{
NSLog(@"%@",str);
}
- (IMP)methodForSelector:(SEL)aSelector
函数的作用是通过SEL生成的ID来查找和定位函数的实现地址。
MyPrint(self,@selector(Print:),@"Hello
World”); 调用MyPrint函数指针所指向的函数。參数分别为receiver,SEL和要传递给函数的參数。
首先,编译器依据函数声明生成一个唯一函数ID,每一个实例变量的第一个成员是isa,它指向类对象,在类对象中保存有该类所拥有的方法列表,通过生成的的函数ID能够找到其相应的函数地址,从而调用函数。 假设在当前类对象的函数映射表中没有找到函数的话,就继续搜索其父类中(每一个类对象的super_class 存储了父类的类对象地址),假设到达其根类还是没找到的话,会报执行时错误。 其步骤例如以下图所看到的:
消息的成功传递依赖于两个重要的要素,通过实例中的 isa指针找到实例所属的类对象,然后通过类对象中的消息映射表找到所要调用的函数。
首先通过传递的selector參数找到消息映射表中的函数。然后调用函数,将实例的地址和參数传递给调用的这 个函数。 最后返回返回值。
类类型的存在使objective-c拥有了执行时识别,动态创建,序列化等机制。
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmd6aGVianV0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
3.消息接收者对象(指向消息接收者对象的指针)以及方法中指定的參数传递给方法实现 IMP。
4.最后。将方法实现的返回值作为该函数的返回值返回。
注:编译器会自己主动插入调用消息函数objc_msgSend。我们无须在代码中显示调用该消息函数。
五 消息传递小结
到这里,我们已经大致明确了Objective-c 中消息的传递的整个过程。 事实上假设你熟悉MFC的话,你会发现Objective-c的执行时和MFC的RTTI挺像的。
下图是MFC的执行时机制,CRuntimeClass相当于Objectiv-c的object_clas类对象,在CRuntimeClass中有指向基类函数的指针。与MFC不同的是object_class没有类似与m_pNext_ClassMFC成员。
1.编译器会将消息转换为对消息函数 objc_msgSend的调用,该函数有两个基本的參数:消息接收者 receiver 和消息相应的方法ID,即SEL, 同一时候接收消息不定參数列表。
以下再做一下具体消息传递过程:
watermark/2/text/aHR0cDovL2Jsb2cuY3Nkbi5uZXQvemhhbmd6aGVianV0/font/5a6L5L2T/fontsize/400/fill/I0JBQkFCMA==/dissolve/70/gravity/Center" alt="">
正由于有像CRuntimeClass和object_class这些类类型的存在才使得它们拥有了执行识别。动态创建。序列化等机制。
下一节将对消息传递做进一步的深层次探究。
IOS -执行时 (消息传递 )的更多相关文章
- iOS执行时工具-cycript
cycript是大神saurik开发的一个很强大的工具,能够让开发人员在命令行下和应用交互,在执行时查看和改动应用.它确实能够帮助你破解一些应用,但我认为这个工具主要还是用来学习其它应用的设计(主要是 ...
- IOS - 执行时 (多态)
一 多态概述 多态指同一操作作用于不同的对象.能够有不同的解释.产生不同的执行结果.它是面向对象程序设计(OOP)的一个重要特征,动态类型能使程序直到执行时才确定对象的所属类.其详细 ...
- iOS开发时,在Xcode中添加多个Targets进行版本控制
在iOS开发中,很可能有以下场景:需要开发多个版本,或因需区分收费版,免费版,或因为网络环境需要区分测试版,发布版,或因渠道不同需要区分企业版,AppStore版等等.解决办法无非就是CheckOut ...
- iOS执行时与method swizzling
C语言是静态语言,它的工作方式是通过函数调用,这样在编译时我们就已经确定程序怎样执行的.而Objective-C是动态语言,它并不是通过调用类的方法来执行功能,而是给对象发送消息,对象在接收到消息之后 ...
- 执行时关闭标识位 FD_CLOEXEC 的作用
首先先回顾 apue 中对它的描述: ① 表示描述符在通过一个 exec 时仍保持有效(书P63,3.14节 fcntl 函数,在讲 F_DUPFD 时顺便提到) ② 对打开文件的处理与每个描述符的执 ...
- 在Xcode 6 beta里编译Cocos2d-x iOS项目时失败
转载 在Xcode 6 beta里编译Cocos2d-x iOS项目时可能会失败,提示如下错误: Undefined symbols for architecture i386: "_fwr ...
- Xamarin.iOS编译时无法连接苹果系统
Xamarin.iOS编译时无法连接苹果系统 错误信息:Unable to connect to Address=’***.***.***.***’ with User=’***’ 即使Vis ...
- NetBeans IDE 7.4 Beta版本build JavaFX时生成的可执行jar包执行时找不到依赖的jar包
现象,执行时抛出java.lang.ClassNotFoundException异常: Executing E:\secondegg\secondegg-reversi\dist\run8022211 ...
- 用JDBC编程的执行时错误及其解决大全
用JDBC编程的执行时错误及其解决 用JDBC编程的执行时错误及其解决 源码: .java.lang.ClassNotFoundException: com.microsoft.jdbc.sqlser ...
随机推荐
- ny220 推桌子
推桌子 时间限制:1000 ms | 内存限制:65535 KB 难度:3 描述 The famous ACM (Advanced Computer Maker) Company has rent ...
- VC++ 知识点
1.寻找文件时,CFileFind类的使用. 2.寻找目录时使用BROWSEINFO,其中包含了用户选中目录的重要信息. 3.LPITEMIDLIST类 4.目录选择对话框的使用SHBrowseFor ...
- http,javascript的编码解码
http,javascript的编码解码 请求与响应的编码应分开分析 两者的编码,解码处理是相对独立的流程 依赖于相对独立的header: request header, response heade ...
- Java-web-j2e学习建议路线【转】
首先要明白Java体系设计到得三个方面:J2SE,J2EE,J2ME(KJAVA).J2SE,Java 2 Platform Standard Edition,我们经常说到的JDK,就主要指的这个,它 ...
- Android开发日记(五)
从服务器端传递多个数据 先在服务器端设置cs文件 using Newtonsoft.Json; using Newtonsoft.Json.Linq; using System; using Syst ...
- 使用 Elasticsearch 实现博客站内搜索
Reference: http://www.open-open.com/lib/view/open1452046497511.html 一直以来,为了优化本博客站内搜索效果和速度,我使用 bing ...
- 【C++程序员学 python】python 之helloworld
我学习C语言之后才学的C++,所以这里写一个简单的helloworld程序. #coding:utf-8 def main(): print "hello world" if __ ...
- JavaScript(js)文件路径字符串中丢失"\"斜线的解决方法
在刚刚的开发过程中,遇到一个JavaScript 文件路径字符串中丢失"\"的问题,解决过程如下: 背景:cs文件中获取一段包含有路径信息的字符串,将此字符串做为参数传递给前台as ...
- 基于jQuery/CSS3实现拼图效果的相册插件
今天我们要来分享一款很酷的jQuery相册插件,首先相册中的图片会以一定的角度倾斜放置在页面上,点击图片缩略图就可以展开图片,并且图片是由所有缩略图拼接而成,图片展开和收拢的动画效果也非常不错.当然图 ...
- SpringMVC 多个数据源 配置多个事物管理器 Multiple Transaction Managers
http://docs.spring.io/spring/docs/3.0.x/spring-framework-reference/html/transaction.html#transaction ...