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方法 ...
随机推荐
- Redis的String操作
set key value [ex 秒数] / [px 毫秒数] [nx] /[xx] 如: set a 1 ex 10 , 10秒有效 Set a 1 px 9000 , 9秒有效 注: 如果ex, ...
- SQL Server ->> 分区表上创建唯一分区索引
今天在读<Oracle高级SQL编程>这本书的时候,在关于Oracle的全局索引的章节里面有一段讲到如果对一张分区表创建一条唯一索引,而索引本身也是分区的,那就必须把分区列也加入到索引列表 ...
- struts使用html:file上传文件的时候文件名乱码解决
<body> <html:form action="/jwid/struts1x/15.3/form/upload.do?action=upload" encty ...
- lua简化cocos2dx的Action动画序列
情景 今天写代码时,又要写一个很常见的动画,就是变大变小模拟那个弹性的赶脚,很常用但写起来挺麻烦,封装一下用起来就简单多了. 当然我也知道有缓动动画(EaseAction)可以实现反弹效果,但这不是重 ...
- word2vec——高效word特征提取
继上次分享了经典统计语言模型,最近公众号中有很多做NLP朋友问到了关于word2vec的相关内容, 本文就在这里整理一下做以分享. 本文分为 概括word2vec 相关工作 模型结构 Count-ba ...
- gitlab的搭建和linux客户端的连接
一.安装 1.新建 /etc/yum.repos.d/gitlab-ce.repo,添加以下内容 1 2 3 4 5 6 7 [gitlab-ce] name=gitlab-ce baseurl=ht ...
- Android 的 init.rc 文件简介【转】
转自:http://blog.csdn.net/yimiyangguang1314/article/details/6268177 init.rc由许多的Action和Service组成.每一个语句占 ...
- linux学习之centos(三):网卡配置
Linux系统版本:Centos 6.5 在linux学习之centos(二):虚拟网络三种连接方式和SecureCRT的使用中,使用远程工具SecureCRT,通过“ifconfig eth0 + ...
- UVa 1225 Digit Counting
题意:给出n,将前n个整数顺次写在一起,统计各个数字出现的次数. 用的最笨的办法--直接统计-- 后来发现网上的题解有先打表来做的 #include<iostream> #include& ...
- OpenERP 安装在Windows server上时间显示不对的解决办法
这个问题一直困扰着我,后台设置关于时区也参考过一些文章(如改配置文件),显示时间总是差8个小时,后来看了上面的文章后才搞定,虽然那个是解决OE7.0的,但原理一样: server\openerp\ad ...