iOS开发-AFNetworking/NSURLSession异步处理

相信对于GitHub上著名的AFNetworking API,一定都不陌生。本文是一篇基础使用的心得,老手请绕行。

AFNetworking与NSURLSession都是依靠block内的代码进行异步处理来得到网络数据(比如by jSON格式),这样做的好处就是不会阻塞主队列的进程,当block内的代码执行完毕时,进行回调处理,回到主队列。这样当需要得到很多网络数据时,不会让用户在一个空白的页面等待很久,可以把不需要网络数据的部分提前加载,增加用户体验。而且现在NSURLConnection这种在主队列操作的方法已经deprecated了,尽量使用这两种异步处理的方式。

以下为AFNetworking的示例代码(使用jSON格式,源为iTunes RSS top 10 songs)

 1 #import "FetchData.h"
 2 #import <AFNetworking/AFNetworking.h>
 3
 4 @implementation FetchData
 5
 6 - (void)fetchData
 7 {
 8     self.resultArray = [[NSMutableArray alloc]init];
 9     AFHTTPRequestOperationManager *manager = [[AFHTTPRequestOperationManager alloc]init];
10     [manager GET:@"https://itunes.apple.com/us/rss/topsongs/limit=10/json" parameters:nil success:^(AFHTTPRequestOperation * _Nonnull operation, NSDictionary *responseObject) {
11         NSDictionary *feed = [responseObject objectForKey:@"feed"];
12         NSArray *entry = [feed objectForKey:@"entry"];
13         for (NSDictionary *detailDict in entry) {
14             [self.resultArray addObject:[detailDict valueForKeyPath:@"title.label"]];
15         }
16         [[NSNotificationCenter defaultCenter]postNotificationName:@"reload" object:self];
17
18
19     } failure:^(AFHTTPRequestOperation * _Nonnull operation, NSError * _Nonnull error) {
20         NSLog(@"%@", [error description]);
21     }];
22 }

关于import AFNetworking API ,链接https://github.com/AFNetworking/AFNetworking

 1 - (void)fetchSessionData
 2 {
 3     self.resultArray = [[NSMutableArray alloc]init];
 4     NSURLSession *session = [NSURLSession sharedSession];
 5     NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/us/rss/topsongs/limit=10/json"];
 6     NSURLRequest *request = [NSURLRequest requestWithURL:url];
 7     NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
 8         NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
 9         NSDictionary *feed = [json objectForKey:@"feed"];
10         NSArray *entry = [feed objectForKey:@"entry"];
11         for (NSDictionary *detailDict in entry) {
12             [self.resultArray addObject:[detailDict valueForKeyPath:@"title.label"]];
13
14         }
15         [[NSNotificationCenter defaultCenter]postNotificationName:@"reload" object:self];
16     }];
17     [dataTask resume];
18 }
[[NSNotificationCenter defaultCenter]postNotificationName:@"reload" object:self];

是关键,因为是异步处理,所以并不知道block内的内容会什么时候完成,由于示例在MVC结构下,所以使用[NSNotificationCenter]来监控block执行情况,如果方法都在一个ViewController中,则将该代码换成[self.tableView reloadData];

这里说明一下原因,因为UIKit控件都是依据所在的viewController存在的,即使属性改为strong,依然会在此viewcontroller消失后也会release,所以如果是MVC结构,在Model文件中,即使初始化了一个viewController的实例,并使其tableView reloadData,重新返回这个viewController时,还是会再初始化这个tableView所以是无效的。

之后是viewController代码

 1 @interface ViewController ()<UITableViewDataSource, UITableViewDelegate>
 2 @property (nonatomic)UITableView *tableView;
 3 @property (nonatomic)FetchData *fetchData;
 4 @end
 5
 6 @implementation ViewController
 7
 8 - (void)viewDidLoad {
 9     [super viewDidLoad];
10     self.tableView = [[UITableView alloc]initWithFrame:self.view.bounds];
11     [self.tableView setDelegate:self];
12     [self.tableView setDataSource:self];
13     [self.view addSubview:self.tableView];
14     self.fetchData = [[FetchData alloc]init];
15     [self.fetchData fetchData];
16
17     [[NSNotificationCenter defaultCenter]addObserver:self selector:@selector(reload) name:@"reload" object:nil];
18 }
19
20 - (void)reload{
21     [self.tableView reloadData];
22     [[NSNotificationCenter defaultCenter]removeObserver:self name:@"reload" object:nil];
23 }
24
25 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
26 {
27     return 1;
28 }
29
30 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
31 {
32     return self.fetchData.resultArray.count;
33 }
34
35 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
36 {
37     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
38     if (!cell) {
39         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
40     }
41     cell.textLabel.text = [self.fetchData.resultArray objectAtIndex:indexPath.row];
42     return cell;
43 }

注意17行,以及20行的reload方法,在调用fetchData方法之后,发出一个观察者,当观察到post出的notification时,则调用reload方法,刷新tableView,实现异步处理

以下是一个NSURLSession版在viewController里实现的方法,与AFNetworking大同小异

 1 - (void)viewDidLoad {
 2     [super viewDidLoad];
 3     self.tableView = [[UITableView alloc]initWithFrame:self.view.bounds];
 4     [self.tableView setDelegate:self];
 5     [self.tableView setDataSource:self];
 6     [self.view addSubview:self.tableView];
 7     [self fetchSessionData];
 8 }
 9
10 - (void)fetchSessionData
11 {
12     self.resultArrayLocal = [[NSMutableArray alloc]init];
13     NSURLSession *session = [NSURLSession sharedSession];
14     NSURL *url = [NSURL URLWithString:@"https://itunes.apple.com/us/rss/topsongs/limit=10/json"];
15     NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
16         NSDictionary *json = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
17         NSDictionary *feed = [json objectForKey:@"feed"];
18         NSArray *entry = [feed objectForKey:@"entry"];
19         for (NSDictionary *detailDict in entry) {
20             //[self.resultArrayLocal addObject:[detailDict valueForKeyPath:@"title.label"]];
21             NSDictionary *title = [detailDict objectForKey:@"title"];
22             NSString *str = [title objectForKey:@"label"];
23             [self.resultArrayLocal addObject:str];
24
25         }
26
27         [self.tableView reloadData];
28     }];
29     [dataTask resume];
30 }
31
32 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
33 {
34     return 1;
35 }
36
37 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
38 {
39     return self.fetchData.resultArray.count;
40 }
41
42 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
43 {
44     UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"cell"];
45     if (!cell) {
46         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cell"];
47     }
48     cell.textLabel.text = [self.fetchData.resultArray objectAtIndex:indexPath.row];
49     return cell;
50 }

主要是想提一下MVC下[NSNotificationCenter]的用法,由此,异步刷新实现

欢迎光临我的主页:http://www.jiachengzhi.com

时间: 2024-11-08 19:19:01

iOS开发-AFNetworking/NSURLSession异步处理的相关文章

iOS开发:AFNetworking和ASIHTTPRequest的比较

标签: it 网络请求 asihttprequest afnetworking   ASI和AFN以及底层框架的关系  对比 ASI AFN 更新状态 2012年10月份,已经停止更新 持续更新中,目前已更新至2.0版 介绍 ASI的直接操作对象ASIHTTPRequest,是一个实现了了NSCopying协议的NSOperation子类. 在initialize和initWithURL:方法中初始化相关属性并配置一系列请求相关参数默认值.此外,ASIHTTPRequest还提供了一系列的实例方

iOS开发 - AFNetworking网络请求

AFNetworking 什么是AFN 全称是AFNetworking,是对NSURLConnection.NSURLSession的一层封装 虽然运行效率没有ASI高,但是使用比ASI简单 在iOS开发中,使用比较广泛 AFN的github地址 https://github.com/AFNetworking/AFNetworking AFHTTPRequestOperationManager 是AFN中最重要的对象之一 封装了HTTP请求的常见处理 GET\POST请求 解析服务器的响应数据

iOS开发 AFNetworking 3.0使用遇到的问题

前段时间写了一个iOS开发之AFNetworking 3.0.4使用这篇文章,是基本的用法,昨天在使用的时候又出现了几个问题,特地俩记录下,希望能帮到大家! 问题一 我是做一个获取手机验证码的功能,进行一个网络请求,验证码也发给我了,后台的也跟我说请求成功了,但是我这边打印信息显示直接进入了错误的回调...如下图: 验证码获取返回格式问题 报错说是返回类型不一致,后来查明原因,是返回的格式问题(虽然后台跟我说返回的json)需要添加上这么一句话: //如果报接受类型不一致请替换一致text/ht

iOS开发swift版异步加载网络图片(带缓存和缺省图片)

iOS开发之swift版异步加载网络图片 与SDWebImage异步加载网络图片的功能相似,只是代码比较简单,功能没有SD的完善与强大,支持缺省添加图片,支持本地缓存. 异步加载图片的核心代码如下:  func setZYHWebImage(url:NSString?, defaultImage:NSString?, isCache:Bool){         var ZYHImage:UIImage?         if url == nil {             return   

iOS开发&gt;学无止境 - Cell异步图片加载优化,缓存机制详解

作者:勤奋的笨老头 网址:http://www.jianshu.com/p/02ab2b74c451 最近研究了一下UITbleView中异步加载网络图片的问题,iOS应用经常会看到这种界面.一个tableView上显示一些标题.详情等内容,在加上一张图片.这里说一下这种思路. 为了防止图片多次下载,我们需要对图片做缓存,缓存分为内存缓存于沙盒缓存,我们当然两种都要实现. 由于tableViewCell是有重用机制的,也就是说,内存中只有当前可见的cell数目的实例,滑动的时候,新显示cell会

iOS开发-AFNetworking的使用

概述 AFNetworking是一个非常受欢迎的轻量级的iOS.Mac OS X网络通信类库.它建立在NSURLConnection.NSOperation以及其技术的基础上,有着精心设计的模块结构和功能丰富的API,让很多网络通信功能的实现变得十分简单. AFNetworking支持HTTP请求和基于REST的网络服务(包括GET.POST. PUT以及DELETE等).支持ARC.AFNetworking项目中还包含一些列单元测试. 要求iOS 5.0及以上版本,或者Mac OS 10.7及

iOS开发-AFNetworking参数和多文件同时上传【多文件上传】

1. 前言 在项目开发中,我们经常需要上传文件,例如:上传图片,上传各种文件,而有时也需要将参数和多个文件一起上传,不知道大家的项目中遇到了没有,我在最近的项目中,就需要这样的一个功能:同时上传参数.多张图片和音频: 2. 功能实现 在实现此功能之前,需要引入第三方AFNetworking,这是一个非常强大的网络开发工具,这里我就不多说了,下面是我用此工具,封装的一个同时上传参数和多个文件的方法: 2.1 方法名 /** 多文件上传,支持同时上传参数.多个图片.多个音频,[需要将每一个文件转化为

iOS开发——AFNetworking框架使用详解

AFNetworking is a delightful networking library for iOS and Mac OS X.It's built on top of the Foundation URL Loading System, extending the powerful high-level networking abstractions built into Cocoa. It has a modular architecture with well-designed,

ios开发多线程篇--异步加载网络图片

一.异步加载网络图片 1.ATS (1)简介 从iOS9.0开始,如果按照以前的方式写代码,在访问网络的时候 ,会报以下警告信息: App Transport Security has blocked a cleartext HTTP (http://) resource load since it is insecure. Temporary exceptions can be configured via your app's Info.plist file. 原因:iOS9.0引入了新特性