什么是回调

看了好多关于回调的解释的资料,一开始总觉得这个概念理解起来有点困难,可能是因为自己很少遇到这种类型的调用吧。探索良久之后,才算有点启发,下面是自己的一点理解。
我们知道,在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学习笔记之回调(一)的更多相关文章

  1. iOS学习笔记之回调(二)

    写在前面 上一篇学习笔记中简单介绍了通过目标-动作对实现回调操作:创建两个对象timer和logger,将logger设置为timer的目标,timer定时调用logger的sayOuch函数.在这个 ...

  2. ios学习笔记block回调的应用(一个简单的例子)

    一.什么是Blocks      Block是一个C级别的语法以及运行时的一个特性,和标准C中的函数(函数指针)类似,但是其运行需要编译器和运行时支持,从ios4.0开始就很好的支持Block. 二. ...

  3. iOS学习笔记10-UIView动画

    上次学习了iOS学习笔记09-核心动画CoreAnimation,这次继续学习动画,上次使用的CoreAnimation很多人感觉使用起来很繁琐,有没有更加方便的动画效果实现呢?答案是有的,那就是UI ...

  4. IOS学习笔记48--一些常见的IOS知识点+面试题

      IOS学习笔记48--一些常见的IOS知识点+面试题   1.堆和栈什么区别? 答:管理方式:对于栈来讲,是由编译器自动管理,无需我们手工控制:对于堆来说,释放工作由程序员控制,容易产生memor ...

  5. iOS学习笔记16-数据库SQLite

    一.数据库 在项目开发中,通常都需要对数据进行离线缓存的处理,如新闻数据的离线缓存等.离线缓存一般都是把数据保存到项目的沙盒中.有以下几种方式: 归档:NSKeyedArchiver 偏好设置:NSU ...

  6. iOS学习笔记13-网络(二)NSURLSession

    在2013年WWDC上苹果揭开了NSURLSession的面纱,将它作为NSURLConnection的继任者.现在使用最广泛的第三方网络框架:AFNetworking.SDWebImage等等都使用 ...

  7. iOS学习笔记——AutoLayout的约束

    iOS学习笔记——AutoLayout约束 之前在开发iOS app时一直以为苹果的布局是绝对布局,在IB中拖拉控件运行或者直接使用代码去调整控件都会发上一些不尽人意的结果,后来发现iOS在引入了Au ...

  8. IOS学习笔记25—HTTP操作之ASIHTTPRequest

    IOS学习笔记25—HTTP操作之ASIHTTPRequest 分类: iOS2012-08-12 10:04 7734人阅读 评论(3) 收藏 举报 iosios5网络wrapper框架新浪微博 A ...

  9. IOS学习笔记之关键词@dynamic

    IOS学习笔记之关键词@dynamic @dynamic这个关键词,通常是用不到的. 它与@synthesize的区别在于: 使用@synthesize编译器会确实的产生getter和setter方法 ...

随机推荐

  1. 脉络清晰的BP神经网络讲解,赞

    学习是神经网络一种最重要也最令人注目的特点.在神经网络的发展进程中,学习算法的研究有着十分重要的地位.目前,人们所提出的神经网络模型都是和学习算 法相应的.所以,有时人们并不去祈求对模型和算法进行严格 ...

  2. Excel有用的宏

    =Index({"同事","同学","亲戚"},b3) 前面的array默认索引从1开始. 如果b3为1.而枚举数组是: 0=>同事, ...

  3. iMpACT中的Xilinx Prom烧录

    2014-01-06 19:56:37 在http://bbs.21ic.com/icview-361925-1-1.html中有比较详细的介绍. 下面的转自:http://xilinx.eetren ...

  4. 感谢大家的支持,发布一个JWFD的补丁文件

    请用这个文件覆盖原来的JWFD开发包里面的同名文件,然后删除JWFD目录下面的那个FLOWTREE.OBJ 文件 然后重启JWFD.... 这个补丁修正了  流程图设计器-树型列表的几个BUG,因为有 ...

  5. 总结Allegro元件封装(焊盘)制作方法[修整]

    总结Allegro元件封装(焊盘)制作方法 在Allegro系统中,建立一个零件(Symbol)之前,必须先建立零件的管脚(Pin).元件封装大体上分两种,表贴和直插.针对不同的封装,需要制作不同的P ...

  6. 标准模板库(STL)学习探究之stack

    标准模板库(STL)学习探究之stack queue priority_queue list map/multimap dequeue string

  7. UUID的具体用法

    String deleteUuid = UUID.randomUUID().toString(); java.util 类 UUID java.lang.Object java.util.UUID 所 ...

  8. 【转】PWM占空比和分辨率

    占空比是接通时间与周期之比冲量相等而形状不同的窄脉冲加在具有惯性的环节上时,其效果基本相同占空比:就是输出的PWM中,高电平保持的时间与该PWM的时钟周期的时间之比,如一个PWM的频率是1000Hz, ...

  9. Qt之QHeaderView自定义排序(终极版)

    简述 本节主要解决自定义排序衍生的第二个问题-将整形显示为字符串,而排序依然正常. 下面我们介绍三种方案: 委托绘制 用户数据 辅助列 很多人也许会有疑虑,平时都用delegate来绘制各种按钮.图标 ...

  10. SQLServer—系统中的内存配置

    前言: 本文讲述32位和64位系统中的内存配置,在SQLServer 2005/2008中,DBA们往往尝试开启AWE来限制内存.但是,在SQLServer2012以后,这个选项将被弃用,所以不能使用 ...