网络请求与数据解析
2015-08-20 17:17
537 查看
同步、异步请求简介
同步请求会在当前线程中执行网络请求操作,一般情况是在主线程执行。主线程默认处理用户交互信息,若执行网络请求,则在请求完成之前用户无法与界面交互
异步请求会新开辟一个线程,并在后台线程中执行请求操作。
后台线程与主线程操作同时执行,不会影响到主线程处理用户界面交互信息。
GET、POST请求方法
GET和POST方法是HTTP请求中的常用方法。GET请求常用于向服务器请求数据资源、POST请求常用于向服务器提交或同步数据。
GET请求的参数会跟在URL后进行传递,请求的数据会附在URL之后,参数可能会被第三方拦截,存在不安全因素。
POST请求参数是拼接在请求报文中的,并且可以进行相应的加密机制,相比GET请求有更好的安全性。
NSURLConnection 简介
NSURLConnection是系统提供的一个网络请求类,可以实现HTTP请求中的GET及POST方法。NSURLConnection也提供了包含同步、异步的请求方式。
NSURLConnection基于NSURLRequest发起一个请求。
NSURLRequest、NSURLConnection关系图:
NSURLRequest初始化:
// 1、便利构造初始化 + (id)requestWithURL:(NSURL *)URL; // 2、init初始化 - (id)initWithURL:(NSURL *)URL;
NSMutableURLRequest属性配置:
// 1、设置请求方式 - (void)setHTTPMethod:(NSString *)method; // 2、设置头部参数 - (void)setValue:(NSString *)value forHTTPHeaderField:(NSString *)field; // 3、设置请求报文 - (void)setHTTPBody:(NSData *)data;
NSURLConnection同步请求实现:
+ (NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse **)response error:(NSError **)error;
NSURLConnection异步请求实现:
- (id)initWithRequest:(NSURLRequest *)request delegate:(id)delegate; + (NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(id)delegate;
NSURLConnectionDelegate及NSURLConnectionDataDelegate提供了大量的接口来处理请求中的状态事件:
// 数据接受完 - (void)connectionDidFinishLoading:(NSURLConnection *)connection; - (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response; // 接收到数据 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data; // 请求数据失败 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error;
XML、JSON数据格式解析
XML数据格式
XML(Extensive Markup Language):可扩展标记语言。XML是网络通信中一种常用的数据交互格式,被设计用来传输和存储数据。
XML文档形成了一种树结构,它从“根部”开始,然后扩展到“枝叶”。
JSON数据格式
JSON(JavaScript Object Notation):JavaScript 对象表示法。JSON 是存储和交换文本信息的语法,类似 XML。
JSON内部采用键值对的形式组合数据,类似于字典,不过JSON最外层也支持数组格式。
JSON 比 XML 更小、更快,更易解析。
JSON支持的数据类型包括数组、字符串、逻辑值、字典、Null等。
XML解析:
系统解析类:NSXMLParse第三方库解析类:GDataXMLNode
GDataXMLDocument —- XML文档
GDataXMLNode —- 节点
GDataXMLElement —- 元素
解析方法:按层次获取元素或节点,然后调用方法获取到指定元素对应的值。
JSON解析:
系统解析类:NSJSONSerialization第三方库解析类:SBJSON、JSONKit 等。
解析方法:在JSON字符串以及JSON对象之间直接进行转化。
使用NSJSONSerialization:
+ (NSData *)dataWithJSONObject:(id)obj options:(NSJSONWritingOptions)opt error:(NSError **)error; + (id)JSONObjectWithData:(NSData *)data options:(NSJSONReadingOptions)opt error:(NSError **)error;
案例
tips:本案例中主要解析JSON数据格式;同步/异步 GET请求案例
效果展示代码示例
#import "ViewController.h" // get net:http://apistore.baidu.com/apiworks/servicedetail/112.html // ------------------------ defines #define NSLOG(OBJECT) NSLog(@"%@", OBJECT) #define Get_Url_Apikey @"159d95a8c050074fe3ca0df0d901fc62" #define Get_Url_String @"http://apis.baidu.com/apistore/weatherservice/weather?citypinyin=chengdu" // ------------------------ identifier static NSString *const kUITableViewCellIdentifierGet = @"cellIdentifierGet"; /**< 表格视图标识符Get */ // ------------------------ titles static NSString *const WD = @"风向"; static NSString *const WS = @"风力"; static NSString *const city = @"城市"; static NSString *const cityPinYin = @"城市拼音"; static NSString *const date = @"日期"; static NSString *const fbTime = @"发布时间"; static NSString *const temp = @"当前气温"; static NSString *const h_temp = @"最高气温"; static NSString *const l_temp = @"最低气温"; static NSString *const latitude = @"纬度"; static NSString *const longitude = @"经度"; static NSString *const weather = @"天气"; @interface ViewController () <UITableViewDelegate, UITableViewDataSource, NSURLConnectionDelegate, NSURLConnectionDataDelegate> { NSArray *_getRequestDataTitles; /**< Get请求界面标题 */ NSArray *_getRequestDataKeys; /**< Get请求数据Key */ NSMutableData *_revicedData; /**< 存储接收到的data数据 */ NSMutableArray *_dataSource; /**< 数据源 */ } @property (nonatomic, strong) UITableView *tableView; /**< 表格视图 */ - (void)initializeUserInterface; /**< 初始化用户界面 */ - (void)initializeDataSource; /**< 初始化数据源 */ - (NSMutableURLRequest *)createGetRequest; /**< 创建Get请求 */ - (void)sendSynchronousGetRequet; /**< 发送同步Get请求 */ - (void)sendAsynchronousGetRequest; /**< 发送异步Get请求 */ - (void)analyticalDataOfGetRequestWithData:(NSData *)data; /**< Get请求数据解析 */ @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initializeDataSource]; [self initializeUserInterface]; // 1、发送同步GET请求 // [self sendSynchronousGetRequet]; // 2、发送异步GET请求 [self sendAsynchronousGetRequest]; } #pragma mark- init - (void)initializeDataSource { // 初始化数据源 _dataSource = [NSMutableArray array]; // 初始化数据 _revicedData = [NSMutableData data]; // get数据请求标题 _getRequestDataTitles = @[city,cityPinYin,temp,h_temp,l_temp,weather,longitude,latitude,date,fbTime,WD,WS]; // get数据请求数据key _getRequestDataKeys = @[@"city",@"pinyin",@"temp",@"h_tmp",@"l_tmp",@"weather",@"longitude",@"latitude",@"date",@"time",@"WD",@"WS"]; } - (void)initializeUserInterface { // 关闭系统自动调整滚动视图偏移 self.automaticallyAdjustsScrollViewInsets = NO; // 添加表格视图 [self.view addSubview:self.tableView]; } #pragma mark - request methods // 创建请求 - (NSMutableURLRequest *)createGetRequest { // 创建请求 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:Get_Url_String ]]; // 配置header(ApiKey) [request addValue:Get_Url_Apikey forHTTPHeaderField:@"apikey"]; return request; } // 发送同步GET请求 - (void)sendSynchronousGetRequet { // 创建请求 NSMutableURLRequest *request = [self createGetRequest]; // 创建错误信息 NSError *error = nil; // 发起同步Get请求 NSData *data = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; // 判断是否请求成功 if (error) { NSLOG(error.localizedDescription); }else{ [self analyticalDataOfGetRequestWithData:data]; } } // 发送异步GET请求 - (void)sendAsynchronousGetRequest { // 创建请求 NSMutableURLRequest *requst = [self createGetRequest]; // 发送请求 // 1、需遵守<NSURLConnectionDelegate, NSURLConnectionDataDelegate>; // 2、在代理方法中处理请求回调信息; // 3、协议方法: // didFailWithError:请求失败处理->打印失败信息 // didReceiveData:数据接收处理->拼接数据 // connectionDidFinishLoading:数据接收完毕处理->解析数据 [NSURLConnection connectionWithRequest:requst delegate:self]; } #pragma mark - analytical methods // 解析数据 - (void)analyticalDataOfGetRequestWithData:(NSData *)data { NSError *error = nil; id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error]; // 判断是否解析成功 if (error) { NSLOG(error.localizedDescription); }else{ // 移除数据源 [_dataSource removeAllObjects]; NSDictionary *dict = object[@"retData"]; for (int i = 0; i < _getRequestDataKeys.count; i++) { // 获取数据 id value = [dict objectForKey:_getRequestDataKeys[i]]; // 判断数据是否为NSNumber类型,如果是,则转成字符串类型 if ([value isKindOfClass:[NSNumber class]]) { value = [NSString stringWithFormat:@"%@", value]; } // 创建字典存储数据 NSDictionary *dataDict = @{_getRequestDataTitles[i] : value}; // 将字典数据存入数据源中 [_dataSource addObject:dataDict]; } [_tableView reloadData]; } } #pragma mark - private methods // 处理网络请求参数 - (NSData *)httpBodyWithParametersDict:(NSMutableDictionary *)parametersDict { // 初始化空字符串 NSMutableString *string = [NSMutableString string]; // for-in循环遍历字典数据 for (NSString *key in parametersDict) { // 拼接参数 [string appendFormat:@"%@=%@&", key, parametersDict[key]]; } // 截取参数多余字符并通过NSUTF8StringEncoding转码为NSData数据类型 return [[string substringToIndex:string.length - 1] dataUsingEncoding:NSUTF8StringEncoding]; } #pragma mark - <NSURLConnectionDelegate, NSURLConnectionDataDelegate> // 请求失败 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLOG(error.localizedDescription); } // 接收到数据 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 拼接数据 [_revicedData appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 解析数据 [self analyticalDataOfGetRequestWithData:_revicedData]; } #pragma mark - UITableViewDataSource methods // 设置行 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } // 设置组 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _dataSource.count; } // 设置单元格 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 表格视图重用机制 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kUITableViewCellIdentifierGet]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue2 reuseIdentifier:kUITableViewCellIdentifierGet]; } // 设置表格无选中样式 cell.selectionStyle = UITableViewCellSelectionStyleNone; // 单元格赋值 cell.textLabel.text = ((NSDictionary *)_dataSource[indexPath.row]).allKeys[0]; cell.detailTextLabel.text = [_dataSource[indexPath.row] objectForKey:_getRequestDataTitles[indexPath.row]]; return cell; } #pragma mark - getter - (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 64) style:UITableViewStylePlain]; // 设置代理 _tableView.delegate = self; // 设置数据源 _tableView.dataSource = self; // 设置尾部视图清除分割线 _tableView.tableFooterView = [UIView new]; } return _tableView; } @end
同步/异步 POST请求案例
备注:程序中Post_Url_Apikey需要自行在聚合数据中注册账号申请;
效果展示
代码示例
#import "ViewController.h" // post net:http://www.juhe.cn/docs/api/id/46/aid/131 // ------------------------ defines #define NSLOG(OBJECT) NSLog(@"%@", OBJECT) #define Post_Url_Apikey @"请输入自己的key" #define Post_Url_String @"http://apis.juhe.cn/cook/queryid" #define Post_Url_Parameter_Id @(1001) #define Post_Url_Parameter_Dtype @"json" // ------------------------ identifier static NSString *const kUITableViewCellIdentifierPost = @"cellIdentifierPost"; /**< 表格视图标识符Post */ @interface ViewController () <UITableViewDelegate, UITableViewDataSource, NSURLConnectionDelegate, NSURLConnectionDataDelegate> { NSMutableData *_revicedData; /**< 存储接收到的data数据 */ NSMutableArray *_dataSource; /**< 数据源 */ } @property (nonatomic, strong) UITableView *tableView; /**< 表格视图 */ - (void)initializeUserInterface; /**< 初始化用户界面 */ - (void)initializeDataSource; /**< 初始化数据源 */ - (NSMutableURLRequest *)createPostRequest; /**< 创建Post请求 */ - (void)sendSynchronousPostRequet; /**< 发送同步Post请求 */ - (void)sendAsynchronousPostRequest; /**< 发送异步Post请求 */ - (void)analyticalDataOfPostRequestWithData:(NSData *)data; /**< Post请求数据解析 */ - (NSData *)httpBodyWithParametersDict:(NSMutableDictionary *)parametersDict; /**< 构造请求参数 */ @end @implementation ViewController - (void)viewDidLoad { [super viewDidLoad]; [self initializeDataSource]; [self initializeUserInterface]; // 1、发送同步POST请求 [self sendSynchronousPostRequet]; // 2、发送异步POST请求 // [self sendAsynchronousPostRequest]; } #pragma mark- init - (void)initializeDataSource { // 初始化数据源 _dataSource = [NSMutableArray array]; // 初始化数据 _revicedData = [NSMutableData data]; } - (void)initializeUserInterface { // 关闭系统自动调整滚动视图偏移 self.automaticallyAdjustsScrollViewInsets = NO; // 添加表格视图 [self.view addSubview:self.tableView]; } #pragma mark - request methods - (NSMutableURLRequest *)createPostRequest { // 创建请求 NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:Post_Url_String]]; // 配置请求 request.timeoutInterval = 10; request.HTTPMethod = @"POST"; // 构造请求参数 NSMutableDictionary *parametersDict = [NSMutableDictionary dictionary]; [parametersDict setObject:Post_Url_Parameter_Id forKey:@"id"]; [parametersDict setObject:Post_Url_Parameter_Dtype forKey:@"dtype"]; [parametersDict setObject:Post_Url_Apikey forKey:@"key"]; // NSData *parametersData = [self httpBodyWithParametersDict:parametersDict]; // 设置请求报文 request.HTTPBody = parametersData; return request; } - (void)sendSynchronousPostRequet { // 创建查询请求 NSMutableURLRequest *request = [self createPostRequest]; // 发送请求 NSError *error = nil; id object = [NSURLConnection sendSynchronousRequest:request returningResponse:nil error:&error]; if (error) { NSLOG(error.localizedDescription); }else{ // 解析数据 [self analyticalDataOfPostRequestWithData:object]; } } - (void)sendAsynchronousPostRequest { // 创建请求 NSMutableURLRequest *request = [self createPostRequest]; // 发送请求 // 1、需遵守<NSURLConnectionDelegate, NSURLConnectionDataDelegate>; // 2、在代理方法中处理请求回调信息; // 3、协议方法: // didFailWithError:请求失败处理->打印失败信息 // didReceiveData:数据接收处理->拼接数据 // connectionDidFinishLoading:数据接收完毕处理->解析数据 [NSURLConnection connectionWithRequest:request delegate:self]; } #pragma mark - analytical methods // 解析数据 - (void)analyticalDataOfPostRequestWithData:(NSData *)data { NSError *error = nil; // JSON数据解析 id object = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:&error]; if (error) { NSLOG(error.localizedDescription); }else{ [_dataSource removeAllObjects]; [_dataSource addObjectsFromArray:(NSArray *)object[@"result"][@"data"][0][@"steps"]]; [_tableView reloadData]; } } #pragma mark - private methods // 处理网络请求参数 - (NSData *)httpBodyWithParametersDict:(NSMutableDictionary *)parametersDict { // 初始化空字符串 NSMutableString *string = [NSMutableString string]; // for-in循环遍历字典数据 for (NSString *key in parametersDict) { // 拼接参数 [string appendFormat:@"%@=%@&", key, parametersDict[key]]; } // 截取参数多余字符并通过NSUTF8StringEncoding转码为NSData数据类型 return [[string substringToIndex:string.length - 1] dataUsingEncoding:NSUTF8StringEncoding]; } #pragma mark - <NSURLConnectionDelegate, NSURLConnectionDataDelegate> // 请求失败 - (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error { NSLOG(error.localizedDescription); } // 接收到数据 - (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data { // 拼接数据 [_revicedData appendData:data]; } - (void)connectionDidFinishLoading:(NSURLConnection *)connection { // 解析数据 [self analyticalDataOfPostRequestWithData:_revicedData]; } #pragma mark - UITableViewDataSource methods // 设置行 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return 1; } // 设置组 - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _dataSource.count; } // 设置单元格 - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { // 表格视图重用机制 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:kUITableViewCellIdentifierPost]; if (!cell) { cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:kUITableViewCellIdentifierPost]; } // 设置表格无选中样式 cell.selectionStyle = UITableViewCellSelectionStyleNone; // 单元格赋值 cell.detailTextLabel.text = @""; cell.imageView.image = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:_dataSource[indexPath.row][@"img"]]]]; cell.textLabel.text = _dataSource[indexPath.row][@"step"]; return cell; } #pragma mark - getter - (UITableView *)tableView { if (!_tableView) { _tableView = [[UITableView alloc] initWithFrame:CGRectMake(0, 64, CGRectGetWidth(self.view.bounds), CGRectGetHeight(self.view.bounds) - 64) style:UITableViewStylePlain]; // 设置代理 _tableView.delegate = self; // 设置数据源 _tableView.dataSource = self; // 设置尾部视图清除分割线 _tableView.tableFooterView = [UIView new]; } return _tableView; } @end
相关文章推荐
- Apache Http Server与Tomcat实现负载均衡和集群
- iOS在进行网络请求的时候的网络状态的响应的判断
- HttpInvoker SSL双向认证远程接口调用
- SharePoint 2013 通过HttpModule 管理视图权限
- httpclient 无信任证书使用https
- http post put patch 总结
- apache http server 安装步骤
- 神经网络编程入门
- (14)[Xamarin.Android] 异步的网络图片下载
- android判断网络是否可用
- tcpdump笔记
- 网络基础知识小小说
- 第一次
- Windows Sockets 网络编程——第十章 支持例程
- BP简单的理解神经网络
- 基于TCP协议实现服务器和客户端的通信程序
- 隐藏 HttpClient 在console的日志
- 再说重写IHttpHandler,实现前后端分离
- NFS网络文件系统
- 我对VMware Workstation虚拟网络VMnet0、VMnet1、VMnet8的理解和图解