標籤:
相信對於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 *)tableView26 {27 return 1;28 }29 30 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section31 {32 return self.fetchData.resultArray.count;33 }34 35 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath36 {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)fetchSessionData11 {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 *)tableView33 {34 return 1;35 }36 37 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section38 {39 return self.fetchData.resultArray.count;40 }41 42 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath43 {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
iOS開發-AFNetworking/NSURLSession非同步處理