SEL-消息机制
int main()
{
Person *p = [[Person alloc] init];
//调用方法
[p test2];
[p performSelector:@selector(test2)];
return ;
}
#import "Person.h" @implementation Person
+ (void)test
{
NSLog(@"test-----");
} - (void)test2
{
// _cmd代表着当前方法 NSString *str = NSStringFromSelector(_cmd); // 会引发死循环
// [self performSelector:_cmd]; NSLog(@"调用了test2方法-----%@", str);
} - (void)test3:(NSString *)abc
{
NSLog(@"test3-----%@", abc);
}
@end

RunTime简称运行时。就是系统在运行的时候的一些机制,其中最主要的是消息机制。对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 )。编译完成之后直接顺序执行,无任何二义性。OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编 译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。只有在真正运行的时候才会根据函数的名称找 到对应的函数来调用。
那OC是怎么实现动态调用的呢?下面我们来看看OC通过发送消息来达到动态调用的秘密。假如在OC中写了这样的一个代码:
|
1
|
[obj makeText]; |
其中obj是一个对象,makeText是一个函数名称。对于这样一个简单的调用。在编译时RunTime会将上述代码转化成
|
1
|
objc_msgSend(obj,@selector(makeText)); |
首先我们来看看obj这个对象,iOS中的obj都继承于NSObject。
|
1
2
3
|
@interface NSObject <nsobject> { Class isa OBJC_ISA_AVAILABILITY;}</nsobject> |
在NSObjcet中存在一个Class的isa指针。然后我们看看Class:
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
|
typedef struct objc_class *Class;struct objc_class { Class isa; // 指向metaclass Class super_class ; // 指向其父类 const char *name ; // 类名 long version ; // 类的版本信息,初始化默认为0,可以通过runtime函数class_setVersion和class_getVersion进行修改、读取 long info; // 一些标识信息,如CLS_CLASS (0x1L) 表示该类为普通 class ,其中包含对象方法和成员变量;CLS_META (0x2L) 表示该类为 metaclass,其中包含类方法; long instance_size ; // 该类的实例变量大小(包括从父类继承下来的实例变量); struct objc_ivar_list *ivars; // 用于存储每个成员变量的地址 struct objc_method_list **methodLists ; // 与 info 的一些标志位有关,如CLS_CLASS (0x1L),则存储对象方法,如CLS_META (0x2L),则存储类方法; struct objc_cache *cache; // 指向最近使用的方法的指针,用于提升效率; struct objc_protocol_list *protocols; // 存储该类遵守的协议 } |
我们可以看到,对于一个Class类中,存在很多东西,下面我来一一解释一下:
Class isa:指向metaclass,也就是静态的Class。一般一个Obj对象中的isa会指向普通的Class,这个Class中存储普通成员变量和对 象方法(“-”开头的方法),普通Class中的isa指针指向静态Class,静态Class中存储static类型成员变量和类方法(“+”开头的方 法)。
Class super_class:指向父类,如果这个类是根类,则为NULL。

下面一张图片很好的描述了类和对象的继承关系:

注意:所有metaclass中isa指针都指向跟metaclass。而跟metaclass则指向自身。Root metaclass是通过继承Root class产生的。与root class结构体成员一致,也就是前面提到的结构。不同的是Root metaclass的isa指针指向自身。
Class类中其他的成员这里就先不做过多解释了,下面我们来看看:
@selector (makeText):这是一个SEL方法选择器。SEL其主要作用是快速的通过方法名字(makeText)查找到对应方法的函数指针,然后调用其函 数。SEL其本身是一个Int类型的一个地址,地址中存放着方法的名字。对于一个类中。每一个方法对应着一个SEL。所以iOS类中不能存在2个名称相同 的方法,即使参数类型不同,因为SEL是根据方法名字生成的,相同的方法名称只能对应一个SEL。
下面我们就来看看具体消息发送之后是怎么来动态查找对应的方法的。
首先,编译器将代码[obj makeText];转化为objc_msgSend(obj, @selector (makeText));,在objc_msgSend函数中。首先通过obj的isa指针找到obj对应的class。在Class中先去cache中 通过SEL查找对应函数method(猜测cache中method列表是以SEL为key通过hash表来存储的,这样能提高函数查找速度),若 cache中未找到。再去methodList中查找,若methodlist中未找到,则取superClass中查找。若能找到,则将method加 入到cache中,以方便下次查找,并通过method中的函数指针跳转到对应的函数中去执行。
SEL-消息机制的更多相关文章
- iOS开发系列--通知与消息机制
概述 在多数移动应用中任何时候都只能有一个应用程序处于活跃状态,如果其他应用此刻发生了一些用户感兴趣的那么通过通知机制就可以告诉用户此时发生的事情.iOS中通知机制又叫消息机制,其包括两类:一类是本地 ...
- [转]runtime 消息机制
原文地址:http://www.jianshu.com/p/f6300eb3ec3d 一.关于runtime 之前在项目中有遇到过用runtime解决改变全局字体的问题,所以再一次感受到了runtim ...
- Objective-C总Runtime的那点事儿(一)消息机制
最近在找工作,Objective-C中的Runtime是经常被问到的一个问题,几乎是面试大公司必问的一个问题.当然还有一些其他问题也几乎必问,例 如:RunLoop,Block,内存管理等.其他的问题 ...
- Objective-C 利用OC的消息机制,使用Method Swizzling进行方法修改
功能:修改父类不可修改函数方法,函数方法交换 应用场景:假如我们使用的他人提供一个的framework,.m已被打包成二进制.a无法修改源码,只留下.h头文件,那假如代码中某个函数出现了问题可以通过这 ...
- Objective-C之消息机制
话说2014年4月编程语言排行榜中Objective-C的使用比又增加了,看来IOS和MAX OS的开发者是真给力呀. 不过个人感觉用不了多久,IOS和Android的开发者收入就不会有那么大的差异了 ...
- Objective-C总Runtime的那点事儿(一)消息机制【转】
RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何 ...
- runtime——消息机制
本文授权转载,作者:Sindri的小巢(简书) 从异常说起 我们都知道,在iOS中存在这么一个通用类类型id,它可以用来表示任何对象的类型 —— 这意味着我们使用id类型的对象调用任何一个方法,编译器 ...
- NSObject头文件解析 / 消息机制 / Runtime解读 (一)
NSObject头文件解析 当我们需要自定义类都会创建一个NSObject子类, 比如: #import <Foundation/Foundation.h> @interface Clas ...
- ios学习路线—Objective-C(Runtime消息机制)
RunTime简称运行时.就是系统在运行的时候的一些机制,其中最主要的是消息机制.对于C语言,函数的调用在编译的时候会决定调用哪个函数( C语言的函数调用请看这里 ).编译完成之后直接顺序执行,无任何 ...
- 快速上手Runtime(一)之消息机制
Runtime简介 Runtime简称运行时.OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制. 对于C语言,函数的调用在编译的时候会决定调用哪个函数. 对于OC的函数,属于动态 ...
随机推荐
- 【技巧】为ComboBox添加自动提示
一.需求来源 最近有个项目用到了ComboBox控件,在演示的时候,要对Word文档中选中部分添加符合DocBook标准的标签,这些标签是DocBook中元素的集合,数据量不多,大概170多个吧,但是 ...
- MySQL 代码开发注意事项----开发高性能的sql
序言 一个服务或者一个程序,由 程序+数据组成.在数据这块,计算机中IO是比CPU要慢得多,为了减少IO,减少CPU运算.我们第一时间会想到索引,但索引为啥会提高效率,因为可以减少IO,在查询的时候不 ...
- JavaScript中让Html页面中循环播放文字
JavaScript中让Html页面中循环播放文字 <html> <head> <meta http-equiv="Content-Type" con ...
- ThinkPHP框架之验证码
Think\Verify类可以支持验证码的生成和验证功能. 下面是最简单的方式生成验证码: $Verify = new \Think\Verify(); $Verify->entry(); 上面 ...
- svn提交时提示 Aborting commit: remains in conflict 解决办法
出现在rename一个目录时,再提交时一直报错 Aborting commit: remains in conflict 使用右键菜单 svn - resolve 即可解决.用cleanup之类的都没 ...
- PHPMailer < 5.2.18 - RCE EXP(Bash)
#!/bin/bash# CVE-2016-10033 exploit by opsxcq# https://github.com/opsxcq/exploit-CVE-2016-10033echo ...
- 【WP8.1】类似“IT之家” 自定义消息 的实现
曾经在WP7.WP8下的消息 使用的都是Coding4Fun.Phone.Toolkit里面的ToastPrompt类来实现的. 现在我们来自己做个类似IT之家的这种效果:从右边弹出,经过几秒后会自动 ...
- GOPATH 使用总结
GOPATH 环境变量用于指定这样一些目录:除 $GOROOT 之外的包含 Go 项目源代码和二进制文件的目录.go install 和 go 工具会用到 GOPATH:作为编译后二进制的存放目的地 ...
- Linux 双网卡绑定
Linux 双网卡绑定 Linux 双网卡绑定双网卡绑定的常用模式:mode1:active-backup 模式,即主备模式.mode0:round-broin 模式,即负载均衡模式(需要交换机配置聚 ...
- bootstarp
我最近在学一个前端框架叫bootstarp.我的老大给了一个bootstarp的模板给我,我看了看感觉没意思.因为那里面的样式,我也会写,所以我就没心思去看,每次只要面板上有的我就搬下来就完了,只要面 ...