iOS学习笔记之回调(一)
什么是回调
看了好多关于回调的解释的资料,一开始总觉得这个概念理解起来有点困难,可能是因为自己很少遇到这种类型的调用吧。探索良久之后,才算有点启发,下面是自己的一点理解。
我们知道,在OSI网络七层模型中,上层可以直接调用下层的代码来为自己服务,这种调用是一种直接调用的方式。但是下层不能直接调用上层的代码,除非上层为下层提供了相应的函数。如果上层为下层提供了相应的函数,那么这个函数就被称为回调函数,下层通过回调函数调用上层的这种方式就是一种“回调”。
我们假定下图中的A代表应用层,B代表操作系统层,那么下图中的流程是:
step1:应用层A首先调用操作系统层B的代码,然后假定应用层A在等待操作系统层B的某个资源,为了让B在资源就位的时候可以通知A,A为B提供了一个函数(假定名为f)
step2:当A等待的资源就位时,B就可以调用函数f来通知A
在这个过程中,A设计了回调函数f,但实际调用回调函数的是B。事实上,A和B可以是同一个对象,为了便于理解和叙述,我们可以将两个实体分开来看。

回调主要的应用场景是:当前运行的应用在等待某个特定的事件,如鼠标移动、触摸事件等,当特定的事件发生后,需要通过某种方式告知正在等待的这个应用。
iOS中的回调
iOS中有三种方式可以实现回调
1、目标-动作
在应用等待前,要求当等待的特定事件发生时,向指定的对象发送某个特定的消息。接收消息的对象是目标,消息的选择器是动作。
2、辅助对象
在应用开始等待前,要求当等待的特定事件发生时,向遵守相应协议的辅助对象发送消息。委托对象和数据源是常见的辅助对象。
3、通告
苹果中有一种称为通告中心的对象。在应用开始等待前,可告知通知中心,某个对象正在等待特定的消息。当应用等待的特定事件发生时,相关的对象会向通知中心发布通告,然后再由通知中心将通告转发给正在等待该通告的对象。
目标-动作对
目标-动作是实现回调的一种较为简单的方式。对上图中的例子来讲,目标就是接收消息的对象,就是在等待某个特定事件的那个对象,因此A是B的目标,而动作就是那个回调函数,因此是A设计的f函数。
选择器
在继续讨论回调前,先简单介绍一下选择器。在iOS中,当某个对象收到消息时,会向该对象的类进行查询,检查是否有与消息名称匹配的方法。该查询过程会沿着继承层次结构向上,直到在某个类中查询到或到达继承的顶层。在查询过程中,要求查询的速度非常快速。如果使用方法的实际名称(可能会很长)进行查询,那么查询速度会很慢。因此,编译器会为每个其接触过的方法附带一个唯一的数字。在实际运行过程中,使用这个数字而不是方法名来查询。这个唯一的数字就成为选择器。通过编译指令@selector,可以得到与方法名相对应的选择器。
为了更加清晰的理解目标-动作对的机制,我们以一个简单的案例来分析。在下面的案例中,我们创建一个拥有NSRunLoop对象和NSTimer对象的应用。每隔2秒,NSTimer对象会向其目标发送指定的动作消息。同时,创建一个类,该类的实例设置为NSTimer对象的目标,如下图所示。

创建的代码如下:
首先创建Logger类作为NSTimer类的目标,在头文件中声明一个sayOuch函数。
Logger.h
@interface Logger : NSObject
- (void)sayOuch:(NSTimer *)t;
@end
在.m文件中实现sayOuch方法,让其在控制台输出一句话,便于观察方法运行结果。
Logger.m
@implementation Logger
- (void)sayOuch:(NSTimer *)t
{
NSLog(@"Ouch!");
}
@end
接下来在main函数中声明两个对象,分别是Logger类的对象logger,和NSTimer类的对象timer。我们把logger对象设置为timer对象的目标。
main
int main(int argc, const char * argv[]) {
@autoreleasepool {
// insert code here...
Logger *logger = [[Logger alloc] init];
NSTimer *timer = [NSTimer
scheduledTimerWithTimeInterval:2.0
target:logger
selector:@selector(sayOuch:)
userInfo:nil
repeats:YES];
[[NSRunLoop currentRunLoop] run];
}
return 0;
}
上述代码中,Logger类设置的函数sayOuch将被NSTimer对象调用,因此这个sayOuch函数就是一个回调函数。对照到A-B那个图来说,这个案例中的NSTimer类是B,它位于下层,而Logger类是上层,它提供了回调函数给下层调用。
总结
在iOS编程中,目标-动作对这种回调方式对用于UI控制器和UI控件之间,这种机制产生的原因是,某些事件不能确定何时发生(例如某个按钮被点击),但是一旦发生之后,就要按照预先定义的回调函数去处理。
iOS学习笔记之回调(一)的更多相关文章
- iOS学习笔记之回调(二)
写在前面 上一篇学习笔记中简单介绍了通过目标-动作对实现回调操作:创建两个对象timer和logger,将logger设置为timer的目标,timer定时调用logger的sayOuch函数.在这个 ...
- ios学习笔记block回调的应用(一个简单的例子)
一.什么是Blocks Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二. ...
- iOS学习笔记10-UIView动画
上次学习了iOS学习笔记09-核心动画CoreAnimation,这次继续学习动画,上次使用的CoreAnimation很多人感觉使用起来很繁琐,有没有更加方便的动画效果实现呢?答案是有的,那就是UI ...
- IOS学习笔记48--一些常见的IOS知识点+面试题
IOS学习笔记48--一些常见的IOS知识点+面试题 1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...
- iOS学习笔记16-数据库SQLite
一.数据库 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等.离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式: 归档:NSKeyedArchiver 偏好设置:NSU ...
- iOS学习笔记13-网络(二)NSURLSession
在2013年WWDC上苹果揭开了NSURLSession的面纱,将它作为NSURLConnection的继任者.现在使用最广泛的第三方网络框架:AFNetworking.SDWebImage等等都使用 ...
- iOS学习笔记——AutoLayout的约束
iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...
- IOS学习笔记25—HTTP操作之ASIHTTPRequest
IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...
- IOS学习笔记之关键词@dynamic
IOS学习笔记之关键词@dynamic @dynamic这个关键词,通常是用不到的. 它与@synthesize的区别在于: 使用@synthesize编译器会确实的产生getter和setter方法 ...
随机推荐
- linux怎么运行.SH文件
执行sh xx.sh命令就可以执行.sh文件了.如果直接执行xx.sh文件,就报权限错误 解决办法:执行chmod u+x xx.sh 来添加执行权限
- python列表推导式详解
推导式是Python中很强大的.很受欢迎的特性,具有语言简洁,简化代码,速度快等优点.推导式包括:1.列表推导式2.字典推导式3.集合推导式4.嵌套列表推导式注意: 字典和集合推导是最近才加入到Pyt ...
- Android模拟器分辨率介绍
转自: http://www.cnblogs.com/xrtd/p/3746935.html 本人喜欢用 HVGA(320x480) Skins:HVGA.HVGA-L.HVGA-P.QVGA-L. ...
- HeadFirst Jsp 14 (Structs)
大的web程序可能很复杂, 分很多”层” 有关 RMI 的部分, 可以参考 headfirst java 中的 RMI 的部分. struts 是一个框架, 框架是一些接口和类的集合, 这些接口和类设 ...
- bzoj4197
这题现场想的思路方向都是对的,但限于现场和实力因素没能A 很显然我们会想到质因数的选取 如果某个质数p被W选了,那G就不能选含有质因子p的数 因此我们不难想到状压质数的选取情况,令f[i][j]为w质 ...
- Qt之HTTPS登录
简述 HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版.即HTTP ...
- EntityFramework:支持同一事务提交的批量删除数据实现思路
一切从一段代码说起... 下面一段代码是最近我在对一EF项目进行重构时发现的. protected override void DoRemove(T entity) { this.dbContext. ...
- UVa 11019 (AC自动机 二维模式串匹配) Matrix Matcher
就向书上说得那样,如果模式串P的第i行出现在文本串T的第r行第c列,则cnt[r-i][c]++; 还有个很棘手的问题就是模式串中可能会有相同的串,所以用repr[i]来记录第i个模式串P[i]第一次 ...
- UVa (一道比较复杂的广搜) 816 Abbott’s Revenge
题意: 给出一个迷宫,在迷宫的节点处,面向某个方向只能向给定的方向转弯.给出起点和终点输出迷宫的最短路径,这里指的是刚刚离开起点的时刻,所以即使起点和终点重合路径也非空. 分析: 用三个变量来表示状态 ...
- LA 2965 Jurassic Remains
这是我做的第一道状态压缩的题目,而且我自己居然看懂了,理解得还算透彻. 题意:给出若干个大写字母组成的字符串,然后选取尽量多的字符串使得这些字母出现偶数次. 最朴素的想法,穷举法:每个字符串只有选和不 ...