@selector()的原理

@selector()选择器在我们的平常开发中用到很多,但是很多人并不清楚他的含义或者原理,还有用选择器来触发一个方法,到底是怎么的个流程,我们今天就来说一说@selector()选择器和OC中的方法调用。本篇涉及一些runtime的知识,可以提前补充一些runtime的知识。

一、基本概念

1、SEL
它是@selector()在OC中的表示,可以说是一种数据类型,在OC中的定义:typedef struct objc_selector *SEL;

2、@selector()
它是selector方法选择器,比如addObject:方法,在OC中使用@selector(addObject:)选择一个方法,本质它是一个根据方法名和参数列表生成的一个唯一的标识(更准确的说是根据方法名hash了的一个字符串值),他能唯一的代表一个方法。

在工程中,不同类中,如果方法名相同,那么这个相同方法名的SEL就是同一个,比如说A类中有-(void)addObject:(NSString *)a;方法,B类中有-(void)addObject:(NSString *)a;方法,那这两个方法的SEL就是同一个。

在工程中,所有的方法的SEL都是放在一个表里的,一个方法名对应一个SEL(即一个字符串)
在寻找方法的时候,不是根据方法的名字 “addObject:” 字符,而是寻找SEL里的字符“abcdefg”,在对比的时候,对比字符串只要对比字符串的地址就可以了,所以速度是很快的。

SEL和方法名.png

3、IMP
IMP是一个函数的地址,指向的是函数实现的地址。
它的定义如下
typedef id (*IMP)(id, SEL, ...);

第一个参数:是指向self的指针(如果是实例方法,则是类实例的内存地址;如果是类方法,则是指向元类的指针)
第二个参数:是方法选择器(selector)
接下来的参数:方法的参数列表。

前面的SEL就是为了加快找到IMP而存在的

4、Method
Method是类定义中的方法,在类的结构中有一个方法的集合的链表,里面存放的都是Method。
Method的定义:

struct objc_method {
    SEL method_name                                          OBJC2_UNAVAILABLE;
    char *method_types                                       OBJC2_UNAVAILABLE;
    IMP method_imp                                           OBJC2_UNAVAILABLE;
}

在结构中可以看到有SEL和IMP,把方法选择器和IMP方法的实现实现了一一对应的关系。

二、SEL的方法

1、SEL的创建
SEL创建有三个方法
1、@selector()创建
2、NSSelectorFromString()
3、sel_registerName()

SEL创建.png

2、SEL的其他方法
使用performSelector来发送消息

[p performSelector:@selector(test)];   
[self performSelector:@selector(addObject:second:) withObject:@"first" withObject:@"second"];

三、消息发送

在内存中每个类的方法都存储在类的结构空间中,每个方法都有一个与之对应的SEL类型的数据,根据一个SEL数据就可以找到对应的方法实现的地址,进而调用方法。

在runtime中方法的调用都是用消息的发送,即
id objc_msgSend(id theReceiver, SEL theSelector, …)

  • theReceiver:第一个参数是消息的接受者
  • theSelector:第二个参数是方法的SEL
  • ...后面的参数是一些方法的参数

在调用方法的时候,比如说[person addObject:@"a"];会转化为objc_msgSend(person, @selector(addObject:), @"a")来发送消息,它会根据person的isa指向的Person类,在Person的类空间结构的方法的cache表中查找是否有该方法(用SEL进行对比),如果有直接返回方法的实现,如果没有会指向superClass,查找是否有该方法,一直往上寻找,如果找到则返回方法的实现,如果没有则抛出异常。

当不同的类选择同一个SEL方法执行的时候,为什么会指向不同的方法实现,最主要的就是因为objc_msSend中的theReceiver不同,根据不同的receiver在不同的类的方法列表中对应的方法实现。

注意:
1、一个类的方法的SEL和IMP是放在一个dispatch table中的,里面是一一对应的关系,所以不允许一个类有相同的SEL方法,当时可以有方法名相同的+方法和-方法,即 -(void)addObject:(NSString *)a+(void)addObject:(NSString *)a 可以同时存在,以为-方法是实例方法,放在类的结构空间的方法列表中,而+方法是类方法,放在其元类的结构空间的方法列表中,所以这个不是同一张表。

2、在同一个类中,不能出现方法名相同的方法,即使参数和返回值都不同也不可以,因为类的结构中SEL和IMP是一一对应的关系,所以也不支持重载。

参考:
http://blog.csdn.net/fengsh998/article/details/8614486

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 212,222评论 6 493
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 90,455评论 3 385
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 157,720评论 0 348
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 56,568评论 1 284
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 65,696评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 49,879评论 1 290
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,028评论 3 409
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 37,773评论 0 268
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,220评论 1 303
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 36,550评论 2 327
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 38,697评论 1 341
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,360评论 4 332
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,002评论 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 30,782评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,010评论 1 266
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 46,433评论 2 360
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 43,587评论 2 350

推荐阅读更多精彩内容