相信对于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