写在前面

上一篇学习笔记中简单介绍了通过目标-动作对实现回调操作:创建两个对象timer和logger,将logger设置为timer的目标,timer定时调用logger的sayOuch函数。在这个例子中,timer的任务比较简单,只完成一项任务:在指定的时刻触发事件。在这种情况下,适合选择目标-动作来实现回调,但这种方式不适合要发送多个回调的情况。

辅助对象

辅助对象是另一种实现回调的方式。在应用开始等待前,要求当等待的特定事件发生时,向遵守相应协议的辅助对象发送消息。委托对象数据源是常见的辅助对象。

案例

假定我们创建一个NSURLConnection对象并从一个给定的url中获取数据,然后等待回调。回调函数被触发的时机包括:获得数据、数据获取完成、获取数据失败等。
可见,如果只是简单的目标-动作队机制,无法实现这些复杂的回调。因此,我们为NSURLConnection对象设置一个辅助对象,这个辅助对象专门负责处理特定事件发生之后的事情,也就是说,当特定的事件发生后,NSURLConnection对象会向辅助对象发送消息。这些消息包含在一套协议中。协议和接口概念有些相似,协议就是一组方法的声明,遵循相应协议的类必须实现协议中的方法(可以只实现部分方法)。
我们假定让Logger类型的对象成为NSURLConnection对象的辅助对象,也就是说,将Logger对象赋给NSURLConne对象的成员变量delegate。Logger类必须实现NSURLConnection协议中的部分活全部方法。关系图如下:

首先更改Logger类的代码,由于要接收数据,因此为Logger类添加一个NSMutableData类型的属性,如下:
Logger.h

@property NSMutableData *incomingData;

然后在Logger.m中实现协议中的部分方法

//收到一定字节数的数据后会被调用
- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data
{
NSLog(@"received %lu bytes", [data length]); if (!self.incomingData) {
self.incomingData = [[NSMutableData alloc] init];
} [self.incomingData appendData: data];
} //最后一部分数据处理完毕后,会被调用
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Got it all!"); NSString *string = [[NSString alloc] initWithData:self.incomingData
encoding:NSUTF8StringEncoding];
self.incomingData = nil;
NSLog(@"string has %lu characters", [string length]); NSLog(@"The whole string is %@", string);
} //获取数据失败时,会被调用
- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error
{
NSLog(@"connection failed: %@",[error localizedDescription]);
self.incomingData = nil;
}

在main函数中创建Logger对象和NSURLConnection,并将前者设置为后者的辅助对象:

Logger *logger = [[Logger alloc] init];

        NSURL *url = [NSURL URLWithString:@"http://www.cnblogs.com/scut-linmaojiang/p/iOS-huidiao-y.html"];

        NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLConnection *fetchConn = [[NSURLConnection alloc]
initWithRequest:request
delegate:logger
startImmediately:YES];

如上所示,当NSURLConnection对象fetchConn从指定url获取数据时,将logger对象设置为它的辅助对象,也就是将logger作为fetchConn对象的委托。fetchCon获取数据过程中的各种状态会触发logger执行对应状态下的方法。利用断点设置,我们可以知道正常情况下,logger执行回调函数的顺序为:
1、接收到数据,执行

- (void)connection:(NSURLConnection *)connection
didReceiveData:(NSData *)data

运行截图如下:

2、最后一部分数据处理完毕,执行

- (void)connectionDidFinishLoading:(NSURLConnection *)connection

运行截图如下:


...

url是上一篇笔记的地址,获取到的数据是以html格式显示的

如果计算机处理断网状态,那么fetchConn将无法获取到数据,此时logger将执行下面的回调函数

- (void)connection:(NSURLConnection *)connection
didFailWithError:(NSError *)error

运行截图如下:

总结

对比目标-动作对机制和辅助对象机制这两种实现回调的方式可知,当某个对象只提供了一个回调函数时,使用目标-动作对较为合适。而当某个对象要提供多个回调函数,也就说要接收多个回调信息时,使用遵循相应协议的辅助对象较为合理。

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
} - (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

iOS学习笔记之回调(二)的更多相关文章

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

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

  2. iOS学习笔记20-地图(二)MapKit框架

    一.地图开发介绍 从iOS6.0开始地图数据不再由谷歌驱动,而是改用自家地图,当然在国内它的数据是由高德地图提供的. 在iOS中进行地图开发主要有三种方式: 利用MapKit框架进行地图开发,利用这种 ...

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

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

  4. iOS学习笔记之回调(一)

    什么是回调 看了好多关于回调的解释的资料,一开始总觉得这个概念理解起来有点困难,可能是因为自己很少遇到这种类型的调用吧.探索良久之后,才算有点启发,下面是自己的一点理解. 我们知道,在OSI网络七层模 ...

  5. iOS学习笔记(十二)——iOS国际化

    开发的移动应用更希望获取更多用户,走向世界,这就需要应用国际化,国际化其实就是多语言.这篇文章介绍Xcode4.5以后的国际化,包括应用名国际化和应用内容国际化.如果是Xcode4.5之前版本请参考. ...

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

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

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

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

  8. React Native 学习笔记--进阶(二)--动画

    React Native 进阶(二)–动画 动画 流畅.有意义的动画对于移动应用用户体验来说是非常必要的.我们可以联合使用两个互补的系统:用于全局的布局动画LayoutAnimation,和用于创建更 ...

  9. iOS学习笔记-精华整理

    iOS学习笔记总结整理 一.内存管理情况 1- autorelease,当用户的代码在持续运行时,自动释放池是不会被销毁的,这段时间内用户可以安全地使用自动释放的对象.当用户的代码运行告一段 落,开始 ...

随机推荐

  1. CentOS软件安装目录查找

    注:一般的软件的默认安装目录在/usr/local或者/opt里,可以到那里去找找. 指令名称:whereis 功能介绍:在特定目录中查找符合条件的文件.这些文件的烈性应属于原始代码,二进制文件,或是 ...

  2. Eclipse插件安装与使用 —— Properties Editor

    一.下载     首先当然是下载插件啦! 下载地址:http://sourceforge.jp/projects/propedit/downloads/40156/jp.gr.java_conf.us ...

  3. asp数据链接

    asp页面的中的数据库连接要进行唯一名称处理,不然页面中多个连接使用时,会出现连接莫名关闭.数据不能写入,但是页面也没报错.asp可以将有数据库连接的地方,提取成单独的函数.在每个方法单独命名数据库连 ...

  4. BZOJ 3172 单词(ac自动机)

    题目链接:http://61.187.179.132/JudgeOnline/problem.php?id=3172 题意:给出n个单词.输出每个单词在所有单词中一共出现多少次? 思路:首先将所有单词 ...

  5. 安卓发展史以及安卓和苹果对比PPT

    此PPT由我们小组协力完成,介绍了Android的发展史以及android与苹果的一些比较.概述了android发展至今的一系列版本,功能的日益完善,它的强大性,灵活性,公开性使其拥有吸引客服的绝大魅 ...

  6. 想找个计算器当本命?来试试UWP应用《纸书科学计算器》

    久违了.上次在博客园发文还是4年前,正是高中参加NOIP的时候.这4年里发生了很多事,乃至再次看到过去的文章时,仿佛看到了自己也不熟悉的风景.最近很想把我的博客重新拾起来,慢慢灌溉,写一些微不足道的技 ...

  7. UVALive 4043 Ants 蚂蚁(二分图最佳完美匹配,KM算法)

    题意: 有n个蚂蚁n棵树,蚂蚁与树要配对,在配对成功的一对之间连一条线段,要求所有线段不能相交.按顺序输出蚂蚁所匹配的树. 思路: 这个题目真是技巧啊,不能用贪心来为每个蚂蚁选择最近的树,这样很可能是 ...

  8. 【C#学习笔记】数组使用

    using System; namespace ConsoleApplication { class Program { static void Main(string[] args) { //int ...

  9. 2015-10-09 Fri 晴 加快进度看书

    最近老感觉每天不够用,每天7点起来,吃饭完了8点开始看书,不知道是我看书太慢了还是时间过得真的很快,不知不觉中午就到了.而这个时候我才看2章的内容,下午能多看3章内容.一本书也就一天的时候,而我现在还 ...

  10. tcp协议中mss的理解

    在介绍MSS之前我们必须要理解下面的几个重要的概念.<blockquote>MTU: Maxitum Transmission Unit 最大传输单元MSS: Maxitum Segmen ...