iOS的网络编程主要涉及两者:客户端和服务器端,上传和下载数据都是客户端通过访问服务器端来实现的。
服务器端开发语言有Java,.Net,C/C++,PHP,Ruby,Python等,而手机客户端的开发语言有OC,Java等与后端开发语言不同,因此要实现服务器端与客户端的数据传输必然要有约定一种数据传输的格式和传输协议,否则二者不能进行交流。这个格式可以为JSON,XML等,传输协议我们熟知的有http(超文本传输协议),它是一个通信规则,注意:这个协议永远都是客户端发起请求,服务器端回送响应。
HTTP请求包:客户端发送一个HTTP请求,是向服务器提交了一个HTTP请求包。
请求包的结构:请求头和请求体。
请求体的数据格式:JSON、XML、符号拼接,客户端向服务器提交的数据都放在请求体中或者后面的URL中。
HTTP请求包包括GET请求和POST请求:
GET请求是客户端向服务器索取数据的一种请求方式,(只包含请求头)。
POST请求是客户端向服务器提交数据的方式,(包含请求头和请求体)。
HTTP响应包:服务器收到请求之后向客户端回应了一个HTTP响应包。
响应包结构:响应头和响应体。
服务器通过响应体将数据传给客户端,数据格式有JSON、XML。
同步请求:数据的请求过程在主线程执行的,网络数据传输的过程会导致主线程堵塞。
异步请求:数据的请求过程在多线程执行的,保持主线程的流畅性,UI界面的渲染与刷新在主线程中,主线程不流畅会导致UI界面卡顿。
下面来点干货
网络组件:NSURLSession可以实现上传,下载,处理认证等工具,能处理http协议中的所用事情。
NSURLSession由NSURLSessionConfiguration和可选代理(optional delegate)构成。再根据你的网络需求通过NSURLSessionTask来创建session。
GET请求:
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)GET:(id)sender {
/*
使用NSURLSession 进行网络请求的几个步骤
1.构造NSURL地址
2.构造请求对象 NSURLRequest
3.构造NSURLSessionConfiguration配置文件,可选
4.构造NSURLSession网络会话对象
5.创建网络任务
6.执行网络任务,发送网络请求
*/
//1
NSURL *url= [NSURL URLWithString:@"http://piao.163.com/m/cinema/list.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
//2 使用URL 创建一个可变的请求对象
NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
//设置请求对象
//请求方式
request.HTTPMethod= @"GET";
//超时时间
request.timeoutInterval=60;
//设置请求头中的参数
// [request setValue:@"1533" forHTTPHeaderField:@"cinema_id"];
//3 创建会话对象 默认的会话
NSURLSession *session= [NSURLSession sharedSession];
//4 创建网络任务
//NSURLSessionTask 抽象类 使用其子类 dataTask,uploadTask,downloadTask
NSURLSessionDataTask *dataTask= [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//判断错误
if (error) {
NSLog(@"请求出错:%@", error);
return;
}
NSError *jsonError=nil;
//Json解析
NSDictionary *dic= [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:&jsonError];
NSString *jsonText= [NSString stringWithFormat:@"%@", dic];
//回到主线程 来刷新文字
[_textView performSelectorOnMainThread:@selector(setText:) withObject:jsonText waitUntilDone:NO];
}];
//5 开启任务
[dataTask resume];
}
POST请求:
#import "ViewController.h"
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITextView *textView;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
}
- (IBAction)POST:(id)sender {
/*
使用NSURLSession 进行网络请求的几个步骤
1.构造NSURL地址
2.构造请求对象 NSURLRequest
3.构造NSURLSessionConfiguration配置文件,可选
4.构造NSURLSession网络会话对象
5.创建网络任务
6.执行网络任务,发送网络请求
*/
NSURL *url= [NSURL URLWithString:@"http://piao.163.com/m/cinema/schedule.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
NSMutableURLRequest *request= [NSMutableURLRequest requestWithURL:url];
//设置POST请求
request.HTTPMethod= @"POST";
request.timeoutInterval=60;
//设置请求体
//cinema_id=1533
NSData *bodyData= [@"cinema_id=1533" dataUsingEncoding:NSUTF8StringEncoding];
request.HTTPBody=bodyData;
NSURLSession *session= [NSURLSession sharedSession];
NSURLSessionDataTask *dataTask= [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
NSDictionary *dic= [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSString *jsonString= [NSString stringWithFormat:@"%@", dic];
[_textView performSelectorOnMainThread:@selector(setText:) withObject:jsonString waitUntilDone:NO];
//获取响应包
//将response 转化为一个子类的HTTPURLResponse
NSHTTPURLResponse *httpResponse= (NSHTTPURLResponse *)response;
//打印状态码
NSLog(@"状态码:%li", httpResponse.statusCode);
//获取响应头
NSDictionary *responseHeader=httpResponse.allHeaderFields;
NSLog(@"响应头:%@", responseHeader);
}];
//开始网络任务
[dataTask resume];
}
NSURLSessionConfiguration配置网络会话
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
//使用NSURLSessionConfiguration 来配置网络会话
/*
1 构造URL地址
2 创建Request对象(可选)
3 构建 NSURLSessionConfiguration 对象
4 通过配置 来构建网络会话
5 创建网络任务
6 开启任务
*/
_data= [NSMutableData data];
//URL
NSURL *url= [NSURL URLWithString:@"http://piao.163.com/m/cinema/list.html?app_id=1&mobileType=iPhone&ver=2.6&channel=appstore&deviceId=9E89CB6D-A62F-438C-8010-19278D46A8A6&apiVer=6&city=110000"];
//NSURLSessionConfiguration
/*
defaultSessionConfiguration; 默认的网络会话类型,会进行自动的缓存
ephemeralSessionConfiguration; 临时会话,不会进行任何缓存
backgroundSessionConfigurationWithIdentifier:(NSString *)identifier 后台会话,可以在程序进入到后台之后,继续网络任务
*/
NSURLSessionConfiguration *config= [NSURLSessionConfiguration defaultSessionConfiguration];
//config的常用设置
//config.requestCachePolicy 设置缓存策略
//config.networkServiceType 网络服务类型
config.timeoutIntervalForRequest=20; //网络超时时间
//config.HTTPAdditionalHeaders 请求头的设置
//config.discretionary 节能设置
config.allowsCellularAccess=YES; //是否使用蜂窝网络数据
//创建会话对象
//delegateQueue:用于指定代理方法所运行的队列
NSURLSession *session= [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//创建网络任务
NSURLSessionDataTask *task= [session dataTaskWithURL:url];
[task resume];
}
#pragma mark - NSURLSessionDataDelegate
//当一次网络请求开始,收到返回的响应头之后所调用的方法
- (void)URLSession:(NSURLSession *)session
dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler {
NSLog(@"response: %@",response);
//将NSURLResponse的对象,强转成子类NSHTTPURLResponse对象
NSHTTPURLResponse *httpResponse= (NSHTTPURLResponse *)response;
NSLog(@"状态码:%li", httpResponse.statusCode);
//completionHandler 完成后的回调
//通过执行此bolck 来设定接下来网络访问
/*
NSURLSessionResponseCancel=0, 取消网络访问,不在读取响应体
NSURLSessionResponseAllow=1, 允许本次网络访问,继续接受数据
NSURLSessionResponseBecomeDownload=2, 转化为downLoadTask
NSURLSessionResponseBecomeStream
*/
completionHandler(NSURLSessionResponseAllow);
}
//响应体的接受
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
//接收到响应体中的数据时 调用的方法
NSLog(@"data.lenght= %li", data.length);
//将每次接收到的数据,拼接到全局变量中
[_data appendData:data];
}
//响应完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
if (error) {
NSLog(@"%@", error);
_data=nil;
} else {
//读取无误,Json解析
NSDictionary *dic= [NSJSONSerialization JSONObjectWithData:_data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"dic= %@", dic);
}
}