iOS中SEL的使用及原理

一、了解SEL前的准备-----isa指针简述

1、一个类就像一个 C 结构,NSObject 声明了一个成员变量: isa。由于 NSObject 是所有类的根类,所以所有的对象都会有一个 isa 的成员变量,而该 isa 变量指向该对象的类(空间)。

2、类在Objective-C中也是一个实体, 由于存在Objective-C 运行环境所有的类将有自己的存储空间。Objective-C 运行环境将为每个类分配空间。这里所说的 isa,正是指向这样一个类的空间, 从而建立类和对象之间的对应关系。

3、类空间(Class)包含了该类定义的成员变量,以及方法实现,,还包含了指向自己父类空间的指针。

4、Class里也有个isa的指针, 指向meteClass(元类)。元类保存了类方法的列表。当类方法被调用时,先会从本身查找类方法的实现,如果没有,元类会向他父类查找该方法。同时注意的是:元类(meteClass)也是类,它也是对象。元类也有isa指针,它的isa指针最终指向的是一个根元类(root meteClass)。根元类的isa指针指向本身,这样形成了一个封闭的内循环。

二、SEL 和 @selector()

1、selector 、 SEL 、@selector

(1)类中的方法以 selector 作为索引。selector 的数据类型是 SEL。

(2)虽然 SEL 定义成 char*(字符串),我们可以把它理解成 int。每个方法的名字对应一个唯一的 int 值。比如, 方法 addObject: 可能对应的是 12,当寻找该方法时,使用的是 selector,而不是名字 @"addObject:"

(3)Objective-C 数据结构中,存在一个 name - selector 的映射表如图 3.16

(4)SEL这个类型本质是类方法的编号(函数地址、函数指针、字符串、int、函数编号)

(5)可以理解 @selector()  就是取类方法的编号, 他的行为基本可以等同C语言的中函数指针,  只不过C语言中,可以把函数名直接赋给一个函数指针,而Object-C的类不能直接应用函数指针,这样只能做一个@selector语法来取。@selector的结果是SEL类型,所以说白了,@selector还是获得方法的编号(地址)。

小白总结:SEL其实是对方法的一种包装  ,  将方法包装成一个SEL类型的数据(selector),去寻找对应的方法地址, 找到方法地址后就可以调用方法,这些都是运行时特性,发消息就是发送selector,然后根据selector找到地址,调用方法。 如果子类中找不到,就向上找,直到找到NSobject,没有就报错。SEL本身就是运行时特性的一个现实运用!

2、方法调用的过程及本质

(1)通俗理解 —— 对象调用方法时的寻找过程(寻找方法的过程): selector选择器机制

  <1>首先把test这个方法名包装成SEL类型的数据(一个selector)
  <2>根据SEL数据找到对应的方法地址  
  <3>根据方法地址调用响应的方法
  <4>注意: 在这个操作过程中有缓存,第一次找的时候是一个一个的找(应该是找到了代码区中,一条条找),消耗性能之后再用到的时候直接使用 (个人理解:应该是放到“类对象”的方法列表中了,这也就不用重复检索了)。

(2)大神理解 ——objec_msgSend()函数

  <1> 在编译的时候, 只要有方法的调用, 编译器都会通过 selector 来查找,所以(假设addObject的selector为12),调用方法:[myObject addObject:yourObject];

  <2>上面将会编译变成:

  objc_msgSend(myObject, 12, yourObject);

  这里,objec_msgSend()函数将会使用 myObjec 的 isa 指针来找到 myObject 的类空间结构并在类空间结构中查找 selector 12 所对应的方法.如果没有找到,那么将使用指向父类的指 针找到父类空间结构进行 selector 12 的查找. 如果仍然没有找到,就继续往父类的父类一 直找,直到找到为止, 如果到了根类 NSObject 中仍然找不到,将会抛出异常。

  <3>通过上面,我们可以看到, 这是一个很动态的查找过程。类的结构可以在运行的时候改变,这样可以很 容易来进行功能扩展,Objective-C 语言是动态语言, 支持动态绑定。

3、SEL的应用举例:

调用方法(本身就是把方法包装的),也可以定义SEL类型的变量,然后把这个变量作为参数

时间: 2024-12-29 11:13:48

iOS中SEL的使用及原理的相关文章

iOS中xib与storyboard原理,与Android界面布局的异同

用文本标记语言来进行布局,用的最多的应该是HTML语言.HTML可以理解为有一组特殊标记的XML语言. 一.iOS中xib与storyboard显示原理 在iOS中主要的布置界面的方式有3种:代码,xib,storyboard. 1. 代码 代码布置界面是万能的,但通常很复杂.布置一个简单的界面可能需要很多行代码,因此十分繁琐. 下面为创建一个按钮的代码,最少也要3行: UIButton *btn = [UIButton buttonWithType:UIButtonTypeContactAdd

iOS中多线程原理与runloop介绍

http://mobile.51cto.com/iphone-403490.htm iOS中多线程原理与runloop介绍 iPhone中的线程应用并不是无节制的,官方给出的资料显示iPhone OS下的主线程的堆栈大小是1M,第二个线程开始都是512KB.并且该值不能通过编译器开关或线程API函数来更改.只有主线程有直接修改UI的能力.……>>详细 兄弟专题:iOS人机交互指南之UI设计基础 1 iOS多线程编程知多少 在iOS的世界里有两种实现多线程的方式: 多线程是一个比较轻量级的方法来

ios中创建可以拖动的view原理和实现详解

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIE

iOS中的应用启动原理

iOS中的应用启动原理 来源: http://m.warting.com/program/201601/127355.html 一.UIApplication  1. 简单介绍 (1)UIApplication对象是应用程序的象征,一个UIApplication对象就代表一个应用程序. (2)每一个应用都有自己的UIApplication对象,而且是单例的,如果试图在程序中新建一个UIApplication对象,那么将报错提示. (3)通过[UIApplicationsharedApplicat

ios中创建可以拖动的view原理和实现详解(含代码)

有时候我们会需要在界面上拖动view;uiview是继承于uiresponder的,所以可以响应触摸相关的事件. 重点是以下一组方法: - (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event - (void)touchesEnded:(NSSet *)touches withEvent:(UIE

iOS中__block 关键字的底层实现原理

在 <iOS面试题集锦(附答案)> 中有这样一道题目: 在block内如何修改block外部变量?(38题)答案如下: 默认情况下,在block中访问的外部变量是复制过去的,即:写操作不对原变量生效.但是你可以加上 __block 来让其写操作生效,示例代码如下: __block int a = 0; void (^foo)(void) = ^{ a = 1; }; foo(); //这里,a的值被修改为1 这是 微博@唐巧_boy的<iOS开发进阶>中的第11.2.3章节中的描述

OS X 和iOS 中的多线程技术(上)

OS X 和iOS 中的多线程技术(上) 本文梳理了OS X 和iOS 系统中提供的多线程技术.并且对这些技术的使用给出了一些实用的建议. 多线程的目的:通过并发执行提高 CPU 的使用效率,进而提供程序运行效率. 1.线程和进程 进程 什么是进程 进程是指在计算机系统中正在运行的一个应用程序 每个进程之间是独立的,每个进程均运行中其专用且受保护的内存空间内 比如同时打开 Xcode .Safari ,系统就会分别启动两个进程 通过活动监视器可以查看Mac系统中所开启的进程 线程 什么是线程 一

IOS热更新-JSPatch实现原理+Patch现场恢复

关于HotfixPatch 在IOS开发领域,由于Apple严格的审核标准和低效率,IOS应用的发版速度极慢,稍微大型的app发版基本上都在一个月以上,所以代码热更新(HotfixPatch)对于IOS应用来说就显得尤其重要. 现在业内基本上都在使用WaxPatch方案,由于Wax框架已经停止维护四五年了,所以waxPatch在使用过程中还是存在不少坑(比如参数转化过程中的问题,如果继承类没有实例化修改继承类的方法无效, wax_gc中对oc中instance的持有延迟释放...).另外苹果对于

iOS 中 run loop 浅析

iOS 中 run loop 浅析 runloop 虽然是与线程想关的重要概念,但 cocoa 中的 runloop 终是用得不多,观相关博文却也未得入门其"why".所以浅习几日,得一粗陋分享浅文,作为笔记,写下其所以然.有不对或错误的地方,还望指教,不甚感激. run loop解惑 线程在执行完后,会被销毁.为了使线程能一直运行,咱们可以在线程里边弄个运行循环(run loop),让线程一直执行: - (void)myThread:(id)sender { while (TRUE)