同步请求
1.
//这种方式请求和响应都包含在内
NSData * data =[NSData dataWithContentsOfURL:url];
2.
//请求类
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:str]];
//响应类
NSURLResponse * response = nil;
//NSError 报错类
NSError * error = nil;
//发送请求
NSData * data = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
//发送请求成功 服务器会给我们发响应 response/报错信息 error
异步请求
1.GET请求
//GET请求 没有设置请求方式 默认是get请求
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:path] cachePolicy:0 timeoutInterval:10];
//发送异步请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//解析过程
id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@”%@”,obj);
}];
//queue 队列/线程
//程序运行会有一个主线程 所有UI的操作都是主线程在做
//[NSOperationQueue mainQueue] 主线程
//completionHandler 返回数据 响应成功 通过block把数据返回回来
2.NSURLConnection Block
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
//设置请求方式
request.HTTPMethod = @”POST”;
//参数放到请求体里面
NSString * str = @”page=1&number=20”;
request.HTTPBody = [str dataUsingEncoding:NSUTF8StringEncoding];
//发送请求
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
//解析
id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
}];
3.NSURLConnection 协议代理
NSURL * url = [NSURL URLWithString:str];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
//发送请求
[NSURLConnection connectionWithRequest:request delegate:self];
*******************协议方法*************
//发送请求成功 服务器响应 会调用这个方法
-(void)connection:(NSURLConnection )connection didReceiveResponse:(NSURLResponse )response{
NSLog(@”%@”,response);
NSHTTPURLResponse * urlResponse = (id)response;
if (urlResponse.statusCode == 200) {
self.muData = [[NSMutableData alloc] init];
}
//清空可变data
self.muData.length = 0;
}
//接收数据会调用这个方法 接收数据是一段一段的 这个方法会被反复调用 数据越大调用次数越多
-(void)connection:(NSURLConnection )connection didReceiveData:(NSData )data{
NSLog(@"接收到数据");
[self.muData appendData:data];
}
//接收数据完毕
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
id obj = [NSJSONSerialization JSONObjectWithData:self.muData options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",obj);
}
//错误
-(void)connection:(NSURLConnection )connection didFailWithError:(NSError )error{
NSLog(@"%@",error);
}
4.NSURLSession
NSURLSession的基本设置
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//配置对象
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
//会话对象
NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
//普通任务
NSURLSessionDataTask * task = [session dataTaskWithRequest:request];
[task resume];
NSURLSession的协议方法
//响应成功 调用该方法
-(void)URLSession:(NSURLSession )session dataTask:(NSURLSessionDataTask )dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
NSLog(@”%@”,response);
//清空可变data容器
self.muData.length = 0;
//****这个block必须要调用****
completionHandler(NSURLSessionResponseAllow);
/*
NSURLSessionResponseCancel = 0, //取消接收数据
NSURLSessionResponseAllow = 1, //继续下载数据
NSURLSessionResponseBecomeDownload = 2, //把数据变成下载
NSURLSessionResponseBecomeStream //变成数据流
*/
}
//这个方法会被多次调用 接收数据会调用这个方法 数据返回的时候是一段一段的
-(void)URLSession:(NSURLSession )session dataTask:(NSURLSessionDataTask )dataTask didReceiveData:(NSData *)data{
//拼接数据
[self.muData appendData:data];
}
//不管下载成功或失败 都会调用这个方法
-(void)URLSession:(NSURLSession )session task:(NSURLSessionTask )task didCompleteWithError:(NSError *)error{
if (error) {
NSLog(@"%@",error);
}
else{
//下载成功 解析数据
id obj = [NSJSONSerialization JSONObjectWithData:self.muData options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",obj);
}
}
NSURLSession Block写法
1.普通任务
//创建session(会话)对象
//创建的是单例对象 这种方式和使用NSURLConnection是一样的
NSURLSession * session = [NSURLSession sharedSession];
//NSURLSessionDataTask普通下载
NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//data我们需要的数据 response响应对象 error报错信息
//解析数据
}];
//completionHandler 响应成功 数据回调的时候会调用这个方法
//执行任务 发送请求
[task resume];
2.普通任务
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// NSURLSessionConfiguration工作配置
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
//defaultSessionConfiguration 默认配置
//ephemeralSessionConfiguration 瞬时会话模式 不考虑缓存配置
//backgroundSessionConfigurationWithIdentifier:@"id" 后台配置
//参数 标识符 可以区分多个后台多个下载任务
//设置超时时间
config.timeoutIntervalForRequest = 10.0;
//允许使用移动蜂窝网络
config.allowsCellularAccess = YES;
//根据电量选择网络,电量充足会选择合适的网络
config.discretionary = YES;
//创建会话对象
NSURLSession * session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
id obj = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",obj);
}];
//执行
[task resume];
3.数据下载
NSURLRequest * request = [NSURLRequest requestWithURL:url];
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *session = [NSURLSession sessionWithConfiguration:config];
NSURLSessionDownloadTask * downloadTask = [session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
//下载的数据会存放到默认缓存的位置 任务一结束 缓存被清空
NSString * str = NSHomeDirectory();
//存放路径+文件名
NSString * path = [str stringByAppendingPathComponent:@"library/text.txt"];
//把本地路径转成NSURL对象
NSURL * url1 = [NSURL fileURLWithPath:path];
//将数据写在本地的路径下
}];
//执行下载任务
[downloadTask resume];
4.数据上传
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@""]];
NSURLSession * session = [NSURLSession sessionWithConfiguration:config];
//第二个参数(fromData) 为需要上传的数据
NSURLSessionUploadTask * task = [session uploadTaskWithRequest:request fromData:nil completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
//返回的第一个参数 是否上传成功 用户id信息等 即服务器返回的数据
//解析
}];
//执行任务
[task resume];
5.普通下载
NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:URL]];
NSProgress * progress = nil;
NSURLSessionDownloadTask * task =
[manager downloadTaskWithRequest:request progress:&progress destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
// destination 这个block需要返回一个NSURL 本地存储文件的url地址
// 参数 targetPath 缓存url
//正常情况下 可需要把文件放到沙盒目录下
NSString * path = @"/Users/qianfeng/Desktop/QQ.dmg";
//fileURLWithPath 拿到的是本地URL的路径
return [NSURL fileURLWithPath:path];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
//任务完成的时候调用
NSLog(@"%@ %@",error,[NSString stringWithContentsOfURL:filePath encoding:NSUTF8StringEncoding error:nil]);
}];
//观察进度
//NSProgress的属性--fractionCompleted 完成进度
[progress addObserver:self forKeyPath:@"fractionCompleted" options:NSKeyValueObservingOptionNew context:nil];
[task resume];
6.断点续传 Demo
功能实现: 点击开始按钮 开始下载 ,点击暂停,停止下载 再次点击开始的时候继续下载。当程序中断退出再次进入的时候,可以继续上次的内容下载。
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UIButton *startBtn;
@property (weak, nonatomic) IBOutlet UIButton *stopBtn;
@property (weak, nonatomic) IBOutlet UILabel *proLabel;
@property (weak, nonatomic) IBOutlet UIProgressView *progress;
@property (nonatomic,strong) NSURLSessionDataTask *task;
@property (nonatomic,assign) unsigned long long nowSize;//当前下载文件的大小 文件的字节数
@property (nonatomic,assign) unsigned long long fileSize;//总的文件的大小/字节数
@property (nonatomic,strong) NSFileHandle * handle;
@end
@implementation ViewController
(void)viewDidLoad {
[super viewDidLoad];
self.nowSize = 0;
[self addObserver:self forKeyPath:@”nowSize” options:NSKeyValueObservingOptionNew context:nil];
//读取本地总的字节数
self.fileSize = [[[NSUserDefaults standardUserDefaults] objectForKey:@”fileSize”] integerValue];
//当前已下载的字节数
//NSFileManager 是一个单例对象
NSFileManager * manager = [NSFileManager defaultManager];
//fileExistsAtPath 当前路径下的文件是否存在
if (![manager fileExistsAtPath:@”/Users/qianfeng/Desktop/QQ1.dmg”]) {
[manager createFileAtPath:@”/Users/qianfeng/Desktop/QQ1.dmg” contents:nil attributes:nil];
}
NSDictionary * dic = [manager attributesOfItemAtPath:@”/Users/qianfeng/Desktop/QQ1.dmg” error:nil];
//当前已经下载的字节数
self.nowSize = [dic[@”NSFileSize”] integerValue];
}
(IBAction)onClickStart:(id)sender {
NSURLSessionConfiguration * config = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession * session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[NSOperationQueue mainQueue]];
NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:URL]];
//设置请求头—RANGE
[request setValue:[NSString stringWithFormat:@”bytes=%lld-“,self.nowSize] forHTTPHeaderField:@”RANGE”];
self.task = [session dataTaskWithRequest:request];
[self.task resume];
//开始按钮停止点击功能
[sender setEnabled:NO];
}
(IBAction)onClickStop:(id)sender {
[self.startBtn setEnabled:YES];
[self.task cancel];
}
//请求成功 收到响应的时候
-(void)URLSession:(NSURLSession )session dataTask:(NSURLSessionDataTask )dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
//NSURLResponse 响应对象 NSHTTPURLResponse是NSURLResponse的子类 allHeaderFields拿到所有的响应头
NSDictionary * dic = [(NSHTTPURLResponse *)response allHeaderFields];
NSLog(@”收到数据…%@”,dic);
unsigned long long lastSize = [dic[@"Content-Length"] intValue];
//总大小
self.fileSize = lastSize + self.nowSize;
//将总的大小存在本地
NSUserDefaults * defaults = [NSUserDefaults standardUserDefaults];
[defaults setValue:@(self.fileSize) forKey:@"fileSize"];
[defaults synchronize];
//NSFileHandle写文件
self.handle = [NSFileHandle fileHandleForUpdatingAtPath:@"/Users/qianfeng/Desktop/QQ1.dmg"];
//定位到文件尾部 每一次都是接着上一次写
[self.handle seekToEndOfFile];
//必须调用这个block
completionHandler(NSURLSessionResponseAllow);
}
//实时拿到数据
-(void)URLSession:(NSURLSession )session dataTask:(NSURLSessionDataTask )dataTask didReceiveData:(NSData *)data{
NSLog(@”拿到数据…”);
//计算当前下载的数据大小
self.nowSize += data.length;
//写文件
[self.handle writeData:data];
}
-(void)URLSession:(NSURLSession )session task:(NSURLSessionTask )task didCompleteWithError:(NSError *)error{
//关闭写文件
[self.handle closeFile];
if (error) {
self.startBtn.enabled = YES;
NSLog(@”%@”,error);
}
else{
NSLog(@”下载完成”);
}
}
//观察数据变化
-(void)observeValueForKeyPath:(NSString )keyPath ofObject:(id)object change:(NSDictionary )change context:(void *)context{
float value = self.nowSize*1.0/self.fileSize;
self.progress.progress = value;
self.proLabel.text = [NSString stringWithFormat:@"%.2f%%",value*100];
}