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方法 ...
随机推荐
- 我们为什么需要DTO(数据传输对象)
原文:http://www.cnblogs.com/Gyoung/archive/2013/03/23/2977233.html DTO即数据传输对象(Data Transfer Object).之前 ...
- 生成n对括号的所有合法排列
实例 n = 3,所有的合法序列 ((())) (()()) (())() ()(()) ()()() 思路 针对一个长度为2n的合法排列,第1到2n个位置都满足如下规则 左括号的个数≥右括号的个数 ...
- json 字符串转换成对象,对象转换成json字符串
json 字符串转换成对象,对象转换成json字符串 前端: 方法一: parseJSON方法: [注意jquery版本问题] var str = '{"name":&qu ...
- Ubuntu 12.04 LTS(64bit) 环境下JDK、 Eclipse、 ADT、 快捷图标
一.在FriendlyARM,Tiny4412,,安装包下可补充: (按照手册添加openjdk-6-jdk 后) 安装JDK (Java),选择需要的JDK,或者全部安装. a) OpenJDK-6 ...
- [Golang]使用自建代理访问指定网站
由于爬虫过于频繁访问某一个网站而被禁ip,只因为贪恋一时爽快而忘记了使用代理,这大概是大多数爬虫初学者遇到的问题吧.但是有一些网站不只是爬虫需要访问,人也是需要访问的.这时候就需要使用代理服务器来访问 ...
- [转]深入hibernate的三种状态
学过hibernate的人都可能都知道hibernate有三种状态,transient(瞬时状态),persistent(持久化状态)以及detached(离线状态),大家伙也许也知道这三者之间的区别 ...
- apiCloud创建APP项目
1.注册一个apiCloud账户 2.创建一个应用 3.安装sublime插件 4.用sublime创建应用 5.配置参数,保证一致 6.上传代码,两种方式 一种是压缩成zip 一种是配置svn,通过 ...
- laravel重要概念和知识点
Service Provider: 一个laravel service provider就是一个注册IoC container binding的类.实际上,laravel本身就自包含了一堆管理核心框架 ...
- 用FireMonkey写QQ皮肤
这是运行在Windows平台的效果,同样不需要改一行代码就可以运行在Mac Os,并且效果完全相同: 用FireMonkey做界面速度非常快,其提供的Effect ,Filter,Animation等 ...
- HDU 1907 (博弈) John
参见上一篇博客,里面有分析和结论. #include <cstdio> int main() { int T; scanf("%d", &T); while(T ...