网络编程

一、NSURLConnection
注:在IOS9.0后NSURLConnection已被启用
1.”’GET’请求

//利用NSURLConnection进行"GET"网络请求
-(void)GetTheDataByNSURLConnection{
    //创建URL,网络请求地址
    NSURL * url = [NSURL URLWithString:@"请求的网络地址"];
    //创建网络请求,默认为GET
    NSURLRequest * request = [NSURLRequest requestWithURL:url];
    NSURLResponse * response = nil;
    NSError * error = nil;
    /*
     1.Request:请求对象
     2.Response:若请求成功,则response会有值
     3.Error:若请求出错,则error会有值
     同步请求数据,在主线程执行,可能导致主线程卡顿
     用NSData接受请求到的数据
     */
    NSData * resultData = [NSURLConnection sendSynchronousRequest:request returningResponse:&response error:&error];
    NSLog(@"the result is = %@",[[NSString alloc]initWithData:resultData encoding:NSUTF8StringEncoding]);
}

2.”POST”请求

//利用NSURLConnection进行"POST"网络请求
-(void)PostTheDataByNSURLConnection{
    //创建URL,网络请求地址
    NSURL * url = [NSURL URLWithString:@"请求的网络地址"];
    //创建可变的网络请求,以修改请求方法
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    //POST 请求方法,注:要大写字母
    request.HTTPMethod = @"POST";
    //设置参数,参数之间用 & 隔开
    NSString * bodyStr = [NSString stringWithFormat:@"accountID=%@&password=%@",@"123",@"123"];
    //转化为Data
    NSData * bodyData = [bodyStr dataUsingEncoding:NSUTF8StringEncoding];
    //设置请求体
    request.HTTPBody = bodyData;
    //设置请求头,请求头按照请求内容的规定写入
    [request setValue:@"要发送的请求头内容" forHTTPHeaderField:@"请求头"];
    //设置请求超时
    request.timeoutInterval = 10.0;
    /*
     1.Request:请求对象
     2.queue:代码块Block在此队列中执行
     3.Block代码块:response为响应头,请求成功则有值;data为响应体,解析已得到需要的数据;connectionError为连接出错,若请求出错,则connectionError会有值
     异步请求数据,不会导致主线程卡顿
     */
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        //若请求成功
        if (!connectionError) {
            NSLog(@"the result is = %@",[[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding]);
        }

    }];
}

注:异步请求还可通过代理方法实现,遵循NSURLConnectionDataDelegate协议

二、NSURLSession
1.”GET”请求

-(void)GetFromNetWorkByNSURLSession{
    //创建URL
    NSURL * url = [NSURL URLWithString:@"请求地址"];
    /*创建请求Request,默认为'GET'方式,
     1.URL:请求地址
     2.cachePolicy:缓存策略
        **缓存策略包括**
        1.NSURLRequestUseProtocolCachePolicy:缓存策略的逻辑定义在协议中实现
        2.NSURLRequestReloadIgnoringLocalCacheData:忽视本地缓存数据,从原地址加载数据
        3.NSURLRequestReturnCacheDataElseLoad:若本地有缓存,无论数据是否过期,从缓存中获取;若无缓存数据,则从原地址加载
        4.NSURLRequestReturnCacheDataDontLoad:若本地有缓存,无论数据是否过期,从缓存中获取;若无缓存数据,则加载失败,类似于离线模式
        5.NSURLRequestReloadIgnoringLocalAndRemoteCacheData:不仅忽视本地缓存,只要协议允许,它的代理或其它媒介也被命令忽视缓存,*****尚未实现的
        6.NSURLRequestReloadIgnoringCacheData:是NSURLRequestReloadIgnoringLocalCacheData以前的名字
        ***************
     3.timeoutInterval:请求超时时间
     */
    NSURLRequest * request = [[NSURLRequest alloc]initWithURL:url cachePolicy:(NSURLRequestReturnCacheDataElseLoad) timeoutInterval:10];
    NSURLSession * session = [NSURLSession sharedSession];
    //创建任务,data为响应体,response为响应头
    NSURLSessionDataTask * task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        if (error == nil) {
//            NSString * dataString = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];
//            NSLog(@"data 转 string = %@",dataString);
            //响应体需JSON序列化
            NSJSONSerialization * jsonData = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableContainers) error:nil];
            NSLog(@"json 解析结果 = %@",jsonData);
        }
    }];
    // 或者使用这个方法,自动将url包装成请求对象,仅限GET请求
    // NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
    // NSLog(@"%@---%@",[NSJSONSerialization JSONObjectWithData: data options:kNilOptions error:nil]{
    // }];
    //启动任务
    [task resume];
}

2.”POST”请求

-(void)PostToNetWorkByNSURLSession{
    //创建URL
    NSURL * url = [NSURL URLWithString:@"https://api.weibo.com/2/statuses/update.json"];
    //创建可变请求
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    //设置请求方法
    [request setHTTPMethod:@"POST"];
    //设置请求超时时间
    [request setTimeoutInterval:30];
    //请求体
    NSString * bodyString = @"access_token=23饿3饿3e&status=无限互联";
    NSData * bodyData = [bodyString dataUsingEncoding:NSUTF8StringEncoding];
    //设置请求体
    [request setHTTPBody:bodyData];
    NSURLSession * session = [NSURLSession  sharedSession];
    //同 'GET' 请求相似
    NSURLSessionDataTask * task  = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
        NSJSONSerialization * jsonData = [NSJSONSerialization JSONObjectWithData:data options:(NSJSONReadingMutableContainers) error:nil];
        NSLog(@"json 解析结果 = %@",jsonData);
    }];
    //启动任务
    [task resume];
}

3.代理方法实现NSURLSession
注:需遵循NSURLSessionDataDelegate协议

//代理方法实现网络请求
-(void)GetFromNetWorkWithDelegate{
    NSURL * url = [NSURL URLWithString:@"http://news-at.zhihu.com/api/3/news/latest"];
    NSURLSessionConfiguration * configuartion = [NSURLSessionConfiguration defaultSessionConfiguration];
    configuartion.timeoutIntervalForRequest = 20;
    configuartion.allowsCellularAccess = YES;
    NSOperationQueue * queue = [NSOperationQueue mainQueue];
    NSURLSession * session = [NSURLSession sessionWithConfiguration:configuartion delegate:self delegateQueue:queue];
    NSURLSessionDataTask * task = [session dataTaskWithURL:url];
    [task resume];
}
#pragma mark -- delegateForNSURLSessionDataDelegate
//接受到服务器的响应
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
    //允许接收数据
    completionHandler(NSURLSessionResponseAllow);
    /*
     1.NSURLSessionResponseCancel = 0, // 默认,取消加载数据,等同于[task cancel]
     2.NSURLSessionResponseAllow = 1,   // 允许加载继续
     3.NSURLSessionResponseBecomeDownload = 2,//把请求变为下载
     4.NSURLSessionResponseBecomeStream NS_ENUM_AVAILABLE(10_11, 9_0) = 3,//把任务变成一连串的任务
     */
}
// 接收到服务器返回的数据
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    NSLog(@"正在请求数据。。。。");
}
// 请求完成之后调用该方法
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    NSLog(@"请求结束");
}

三、NSURLSessionConfiguration
NSURLSessionConfiguration对于会话如何产生请求,提供了相当多的控制和灵活性。从网络访问性能,到cookie,安全性,缓存策略,自定义协议,启动事件设置,以及用于移动设备优化的几个新属性。q且配置在初始化时被读取一次,之后都是不会变化的。
1.构造方法
A. “defaultSessionConfiguration”返回标准配置,这实际上与NSURLConnection的网络协议栈是一样的,具有相同的共享NSHTTPCookieStorage,共享NSURLCache和共享NSURLCredentialStorage。
B. “ephemeralSessionConfiguration”返回一个预设配置,没有持久性存储的缓存,Cookie或证书。这对于实现像”无痕浏览”功能的功能来说,是很理想的。
C. “backgroundSessionConfiguration”:独特之处在于,它会创建一个后台会话。后台会话不同于常规的,普通的会话,它甚至可以在应用程序挂起,退出,崩溃的情况下运行上传和下载任务。初始化时指定的标识符,被用于向任何可能在进程外恢复后台传输的守护进程提供上下文。

2.属性
NSURLSessionConfiguration拥有20个属性。最重要的属性:
“HTTPAdditionalHeaders”指定了一组默认的可以设置出站请求的数据头。这对于跨会话共享信息,如内容类型,语言,用户代理,身份认证,是很有用的。

NSString *userPasswordString = [NSString stringWithFormat:@"%@:%@", user, password];

NSData * userPasswordData = [userPasswordString dataUsingEncoding:NSUTF8StringEncoding];

NSString *base64EncodedCredential = [userPasswordData base64EncodedStringWithOptions:0];

NSString *authString = [NSString stringWithFormat:@"Basic: %@", base64EncodedCredential];

NSString *userAgentString = @"iPhone AppleWebKit";

configuration.HTTPAdditionalHeaders = @{@"Accept": @"application/json",@"Accept-Language": @"en",@"Authorization": authString,@"User-Agent": userAgentString};

“networkServiceType(网络服务类型)”对标准的网络流量,网络电话,语音,视频,以及由一个后台进程使用的流量进行了区分。大多数应用程序都不需要设置这个

“allowsCellularAccess(允许蜂窝访问)”和”discretionary(自行决定)”被用于节省通过蜂窝连接的带宽。建议在使用后台传输的时候,使用discretionary属性,而不是allowsCellularAccess属性,因为它会把WiFi和电源可用性考虑在内

“timeoutIntervalForRequest”和”timeoutIntervalForResource”指定了请求以及该资源的超时时间间隔。许多开发人员试图使用timeoutInterval去限制发送请求的总时间,但这误会了timeoutInterval的意思:报文之间的时间。timeoutIntervalForResource实际上提供了整体超时的特性,这应该只用于后台传输,而不是用户实际上可能想要等待的任何东西

“HTTPMaximumConnectionsPerHost”是 Foundation 框架中URL加载系统的一个新的配置选项。它曾经被用于NSURLConnection管理私人连接池。现在有了NSURLSession,开发者可以在需要时限制连接到特定主机的数量

“HTTPShouldUsePipelining”也出现在NSMutableURLRequest,它可以被用于开启HTTP管道,这可以显著降低请求的加载时间,但是由于没有被服务器广泛支持,默认是禁用的

“sessionSendsLaunchEvents” 是另一个新的属性,该属性指定该会话是否应该从后台启动

“connectionProxyDictionary”指定了会话连接中的代理服务器。同样地,大多数面向消费者的应用程序都不需要代理,所以基本上不需要配置这个属性
关于连接代理的更多信息可以在 CFProxySupport Reference 找到。

“Cookie Policies”
-”HTTPCookieStorage” 是被会话使用的cookie存储。默认情况下,NSHTTPCookieShorage的 + sharedHTTPCookieStorage会被使用,这与NSURLConnection是相同的
-”HTTPCookieAcceptPolicy” 决定了该会话应该接受从服务器发出的cookie的条件
-”HTTPShouldSetCookies” 指定了请求是否应该使用会话HTTPCookieStorage的cookie

“Security Policies”
URLCredentialStorage 是会话使用的证书存储。默认情况下,NSURLCredentialStorage 的+ sharedCredentialStorage 会被使用使用,这与NSURLConnection是相同的

“TLSMaximumSupportedProtocol” 和 “TLSMinimumSupportedProtocol” 确定是否支持SSLProtocol版本的会话

“Caching Policies”
URLCache 是会话使用的缓存。默认情况下,NSURLCache 的 + sharedURLCache 会被使用,这与NSURLConnection是相同的
requestCachePolicy 指定了一个请求的缓存响应应该在什么时候返回。这相当于NSURLRequest 的-cachePolicy方法

“Custom Protocols”
protocolClasses是注册NSURLProtocol类的特定会话数组

四、NSURLConnection 文件下载
对于小文件可以直接放在主线程中下载

NSURL * url = [NSURL URLWithString:@"请求URL地址"];
NSData * data = [NSData dataWithContentsOfURL:url];

/*
NSURL * url = [NSURL URLWithString:@"请求地址"];
NSURLRequest * request = [NSURLRequest requestWithURL:url];
[NSURLConnection sendAsynchronousRequest:request queue[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
    NSLog(@"请求数据:%@",data);
}];
*/

对于大文件,加载时间较长,可能需要知道加载的进度,并对它进行暂停操作,且下载的文件需要存储。

#pragma mark -- download
-(void)downLoad{
    //请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
    //创建请求对象,断点下载需要设置请求头,因此要可变的 NSMutableURLRequest;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
    // 设置请求头
    /*
     表示头500个字节:Range: bytes=0-499
     表示第二个500字节:Range: bytes=500-999
     表示最后500个字节:Range: bytes=-500
     表示500字节以后的范围:Range: bytes=500-
     */
    //告知服务器从哪开始下载
    [request setValue:range forHTTPHeaderField:@"Range"];
    //设置代理并发送请求
    _connection = [NSURLConnection connectionWithRequest:request delegate:self];
}
#pragma mark -- DelegateForNSURLConnection
//接收到服务器响应的时候调用
-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{

    if (self.currentLength > 0) {
        return;
    }
    //获取文件总大小,若暂停后继续下载,则获取的是剩余数据的大小
    _totalLength = response.expectedContentLength;
    _fileName = response.suggestedFilename;
    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
    // 获得下载文件路径
    _filePath = [caches stringByAppendingPathComponent:response.suggestedFilename];
    NSFileManager *manager = [NSFileManager defaultManager];
    [manager createFileAtPath:_filePath contents:nil attributes:nil];

    //创建句柄
    _fileHandle = [NSFileHandle fileHandleForWritingAtPath:_filePath];
}
//接收正在加载的数据
-(void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data{
    [_fileHandle seekToEndOfFile];
    [_fileHandle writeData:data];
    _currentLength += data.length;
//    [_fileData appendData:data];
//    _currentLength = _fileData.length;
    CGFloat value = (CGFloat)_currentLength/_totalLength;
    _progressLable.text = [NSString stringWithFormat:@"%.0f%@",value*100,@"%"];
    _progressV.progress = value;

}
//数据加载完毕
-(void)connectionDidFinishLoading:(NSURLConnection *)connection{
    [_downloadBtn setTitle:@"Complete" forState:(UIControlStateNormal)];
    [_fileHandle closeFile];
    _fileHandle = nil;
//    //保存下载的文件到沙盒
//    NSString *caches = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
//    //拼接文件全路径
//    NSString *fullPath = [caches stringByAppendingPathComponent:@"demo.mp4"];
//    //写入数据到文件
//    [_fileData writeToFile:fullPath atomically:YES];
}
//请求失败时调用此方法
-(void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error{
    NSLog(@"Fail");
}

五、NSURLSession 文件下载
对于小文件的下载

NSURL * url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_03.mp4"];
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSURLSessionDownloadTask * task = [session downloadTaskWithURL:url];
    [task resume];

可暂停下载

NSData * resumedata;
    [task cancelByProducingResumeData:^(NSData * _Nullable resumeData) {
        NSLog(@"已下载的数据 = %@",resumeData);
        resumeData = resumeData;
    }];

之后继续下载

task = [session downloadTaskWithResumeData:resumedata];
[task resume];

对于大文件的下载,与NSURLConnection相似,利用代理实现

//请求路径
    NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_02.mp4"];
    //创建请求对象,断点下载需要设置请求头,因此要可变的 NSMutableURLRequest;
    NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
    NSString *range = [NSString stringWithFormat:@"bytes=%zd-",self.currentLength];
    // 设置请求头
    /*
     表示头500个字节:Range: bytes=0-499
     表示第二个500字节:Range: bytes=500-999
     表示最后500个字节:Range: bytes=-500
     表示500字节以后的范围:Range: bytes=500-
     */
    //告知服务器从哪开始下载
    [request setValue:range forHTTPHeaderField:@"Range"];
    //设置代理并发送请求
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    _dataTask = [session dataTaskWithRequest:request];
    #pragma mark -- delegateForSessionData
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler{
    if (_currentLength > 0) {
        return;
    }
    _totalLength = response.expectedContentLength;
    _fileName = response.suggestedFilename;
    _filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:_fileName];
    NSFileManager * manage = [NSFileManager defaultManager];
    [manage createFileAtPath:_filePath contents:nil attributes:nil];
    _handle = [NSFileHandle fileHandleForWritingAtPath:_filePath];
    completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data{
    _currentLength += data.length;
    CGFloat value = (CGFloat)_currentLength/_totalLength;
    _progressLable.text = [NSString stringWithFormat:@"%.0f%@",value*100,@"%"];
    _progressV.progress = value;
    [_handle seekToEndOfFile];
    [_handle writeData:data];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    if (error == nil) {
        [_handle closeFile];
        _handle = nil;
        _playBtn.hidden = NO;
    }
}

六、文件上传
使用NSURLConnection进行文件上传

NSURL * url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    //设置请求头
    NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Boundary];
    [request setValue:header forHTTPHeaderField:@"Content-Type"];
    NSData * bodyData = [self getBody];
    request.HTTPBody = bodyData;
    // 使用代理方法可以监控上传过程
    [NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse * _Nullable response, NSData * _Nullable data, NSError * _Nullable connectionError) {
        NSLog(@"上传完成");

    }];

使用NSURLSession上传文件

-(void)uploadFile{
    NSURL * url = [NSURL URLWithString:@"http://120.25.226.186:32812/upload"];
    NSMutableURLRequest * request = [NSMutableURLRequest requestWithURL:url];
    request.HTTPMethod = @"POST";
    //设置请求头
    NSString *header = [NSString stringWithFormat:@"multipart/form-data; boundary=%@",Boundary];
    [request setValue:header forHTTPHeaderField:@"Content-Type"];
    NSData * bodyData = [self getBody];
    request.HTTPBody = bodyData;
    // 使用代理方法可以监控上传过程
    NSURLSession * session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    _dataTask = [session uploadTaskWithStreamedRequest:request];
}
#pragma mark -- delegateForNSURLSession
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend{
    CGFloat value = (CGFloat)totalBytesSent/totalBytesExpectedToSend;
    _progressV.progress = value;
    _progressLable.text = [NSString stringWithFormat:@"%.0f%@",value*100,@"%"];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error{
    [_uploadBtn setTitle:@"Complete" forState:(UIControlStateNormal)];
}

具体的相关代码可在GitHub下载
https://github.com/Gwyneth143/NSURL.git

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值