1.NSURLSession優(yōu)勢(shì)在哪询吴。(為什么要使用NSURLSession來(lái)替代NSURLConnection)
1.1 下載速度
在2015年RFC 7540正式發(fā)表了下一代HTTP協(xié)議衔肢,是1999年以來(lái)HTTP/1.1發(fā)布后的首個(gè)更新叽粹。相對(duì)HTTP1.1,HTTP/2更加快速份企。
HTTP/2比HTTP/1.1在速度上快很多,iOS9開始,NSURLSession開始全面的支持HTTP/2。
1.2 能夠暫停和恢復(fù)網(wǎng)絡(luò)操作
使用NSURLSession API能夠暫停徐许,停止,恢復(fù)所有的網(wǎng)絡(luò)任務(wù)卒蘸,再也完全不需要子類化NSOperation. 并且默認(rèn)任務(wù)運(yùn)行在其他非主線程中雌隅。
1.3 提高認(rèn)證處理
認(rèn)證是在一個(gè)指定的連接基礎(chǔ)上完成的。在使用NSURLConnection時(shí)缸沃,如果發(fā)出一個(gè)訪問(wèn)恰起,會(huì)返回一個(gè)任意的request。此時(shí)趾牧,你就不能確切的知道哪個(gè)request收到了訪問(wèn)村缸。而在NSURLSession中,就能用代理處理認(rèn)證武氓。
1.4 可配置的容器
對(duì)于NSURLSession里面的requests來(lái)說(shuō)梯皿,每個(gè)NSURLSession都是可配置的容器。舉個(gè)例來(lái)說(shuō)县恕,假如你需要設(shè)置HTTP header選項(xiàng)东羹,你只用做一次,session里面的每個(gè)request就會(huì)有同樣的配置忠烛。
2.NSURLSession介紹属提。
2.1NSURLSession類繼承關(guān)系
在NSURLSession中,網(wǎng)絡(luò)請(qǐng)求基本由3個(gè)任務(wù)完成:
1.NSURLSessionData:請(qǐng)求數(shù)據(jù)任務(wù)
2.NSURLSessionUploadTask:請(qǐng)求上傳任務(wù)
3.NSURLSessionDownloadTask:請(qǐng)求下載任務(wù)
2.2NSURL代理協(xié)議類繼承關(guān)系
2.3NSURLSession使用步驟
1.創(chuàng)建一個(gè)URL
NSURL *url = [NSURL URLWithString:@"協(xié)議://主機(jī)地址/路徑?參數(shù)&參數(shù)"];
2.創(chuàng)建NSURLRequest請(qǐng)求
NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.0];
url:資源路徑
cachePolicy:緩存策略美尸。(無(wú)論使用哪種緩存策略冤议,都會(huì)在本地緩存數(shù)據(jù)) NSURLRequestUseProtocolCachePolicy = 0 //默認(rèn)的緩存策略,使用協(xié)議的緩存策略 NSURLRequestReloadIgnoringLocalCacheData = 1 //每次都從網(wǎng)絡(luò)加載 NSURLRequestReturnCacheDataElseLoad = 2 //返回緩存否則加載师坎,很少使用 NSURLRequestReturnCacheDataDontLoad = 3 //只返回緩存恕酸,沒(méi)有也不加載,很少使用
timeoutInterval:超時(shí)時(shí)長(zhǎng)胯陋,默認(rèn)60s.
注意:request還可以設(shè)置一些其他的信息蕊温,比如請(qǐng)求頭,請(qǐng)求體等遏乔。此時(shí)的request要為NSMutableRequest類型义矛。
// 告訴服務(wù)器數(shù)據(jù)為json類型
[request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
// 設(shè)置請(qǐng)求體(json類型)
NSData *jsonData = [NSJSONSerialization dataWithJSONObject:@{@"userid":@"123456"} options:NSJSONWritingPrettyPrinted error:nil];
request.HTTPBody = jsonData;
3.創(chuàng)建會(huì)話:NSURLSession
4.通過(guò)會(huì)話創(chuàng)建務(wù):NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask
5.調(diào)用resume方法啟動(dòng)任務(wù)。(每一個(gè)任務(wù)都是默認(rèn)掛起的盟萨,需要調(diào)用resume方法)
3.NSURLSession具體使用凉翻。
3.1 NSURLSessionDataTask進(jìn)行GET請(qǐng)求
//1.創(chuàng)建URL
NSURL *url = [NSURL URLWithString:@"http://test.igenshang.com:8001/openapi/api/event/addEventRecord?"];
//2.NSMutableURLRequest
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:NSURLRequestUseProtocolCachePolicy timeoutInterval:30.f];
request.HTTPMethod = @"GET";
//3.創(chuàng)建NSURLSession對(duì)象(使用一個(gè)全局會(huì)話對(duì)象)
NSURLSession *session = [NSURLSession sharedSession];
//4.通過(guò)會(huì)話創(chuàng)建任務(wù)
NSURLSessionDataTask *task = [session dataTaskWithURL:url completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
if (!error) {
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableContainers error:nil];
NSLog(@"%@",dict);
}
}];
//5.啟動(dòng)任務(wù)
[task resume];
4.會(huì)話Session控制。
一般情況下全局的Session我們夠用了捻激,但是如果遇到兩個(gè)連接使用不同配置的情況制轰,就得重新配置session
NSURLSession支持的3種會(huì)話配置
1.defaultSessionConfiguration (default)
進(jìn)程內(nèi)會(huì)話(默認(rèn)會(huì)話),用硬盤來(lái)緩存數(shù)據(jù)
2.ephemeralSessionConfiguration (ephemeral)
臨時(shí)的進(jìn)程內(nèi)會(huì)話铺罢,不會(huì)將cookie,緩存儲(chǔ)存到本地艇挨,只會(huì)放在內(nèi)存中,當(dāng)應(yīng)用程序退出后數(shù)據(jù)也會(huì)消失韭赘。(瀏覽器的無(wú)痕瀏覽模式)
3.backgroundSessionConfiguration (background)
后臺(tái)會(huì)話缩滨,相比默認(rèn)會(huì)話,該會(huì)話會(huì)在后臺(tái)開啟一個(gè)線程進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)處理泉瞻。
配置一個(gè)默認(rèn)session
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 5.0f;//請(qǐng)求超時(shí)時(shí)間
sessionConfig.allowsCellularAccess = true;//是否允許蜂窩網(wǎng)絡(luò)下載(2G/3G/4G)
//創(chuàng)建會(huì)話脉漏,指定配置和代理
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
NSURLSession代理協(xié)議
NSURLSessionDelegate:NSObject
會(huì)話父協(xié)議
NSURLSessionTaskDelegate:NSURLSessionDelegate
任務(wù)協(xié)議
NSURLSessionDataDelegate:NSURLSessionTaskDelegate
數(shù)據(jù)協(xié)議
NSURLSessionDownloadDelegate: NSURLSessionTaskDelegate
下載協(xié)議
NSURLSessionStreamDelegate:NSURLSessionTaskDelegate
網(wǎng)絡(luò)流協(xié)議
NSURLSessionDownloadDelegate 協(xié)議(常用)
/**
* 1.下載中會(huì)多次調(diào)用
*
* @param session 會(huì)話
* @param downloadTask 下載任務(wù)
* @param bytesWritten 此次下載完成的字節(jié)數(shù)
* @param totalBytesWritten 已經(jīng)下載完成的總字節(jié)數(shù)
* @param totalBytesExpectedToWrite 需要下載完成的總字節(jié)數(shù)
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(nonnull NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
/**
* 2.成功下載后調(diào)用
*/
- (void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
/**
* 3.任務(wù)完成后調(diào)用,不管下載是否成功
*/
- (void)URLSession:(NSURLSession *)session
task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
NSURLSessionTask 任務(wù)操作方法
1.取消任務(wù)
- (void)cancel;
2.掛起任務(wù)(暫停任務(wù))
- (void)suspend;
3.啟動(dòng)任務(wù)
- (void)resume;
使用DownloadTask 自制Configuration 代碼
-(void)downloadFile{
1.創(chuàng)建url
NSString *fileName = _textField.text;
NSString *urlStr = [NSString stringWithFormat: @"http://192.168.1.208/FileDownload.aspx?file=%@",fileName];
urlStr = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlStr];
2.創(chuàng)建request
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
3.創(chuàng)建session
3.1創(chuàng)建configuration
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
sessionConfig.timeoutIntervalForRequest = 5.0f;//請(qǐng)求超時(shí)時(shí)間
sessionConfig.allowsCellularAccess = true;//是否允許蜂窩網(wǎng)絡(luò)下載(2G/3G/4G)
3.2創(chuàng)建session
NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
4.創(chuàng)建任務(wù)
_downloadTask = [session downloadTaskWithRequest:request];
5.啟動(dòng)任務(wù)
[_downloadTask resume];
}
pragma mark 點(diǎn)擊取消下載
-(void)cancelDownload{
[_downloadTask cancel];
}
pragma mark 點(diǎn)擊掛起下載
-(void)suspendDownload{
[_downloadTask suspend];
}
pragma mark 點(diǎn)擊恢復(fù)下載
-(void)resumeDownload{
[_downloadTask resume];
}
pragma mark - 下載任務(wù)代理
pragma mark 下載中(會(huì)多次調(diào)用,可以記錄下載進(jìn)度)
-(void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
[self setUIStatus:totalBytesWritten expectedToWrite:totalBytesExpectedToWrite];//設(shè)置界面狀態(tài)
}
pragma mark 下載完成
-(void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didFinishDownloadingToURL:(NSURL *)location
{
NSError *error;
NSString *cachePath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
NSString *savePath = [cachePath stringByAppendingPathComponent:_textField.text];
NSURL *saveUrl = [NSURL fileURLWithPath:savePath];
[[NSFileManager defaultManager] copyItemAtURL:location toURL:saveUrl error:&error];
}
pragma mark 任務(wù)完成袖牙,不管是否下載成功
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error
{
[self setUIStatus:0 expectedToWrite:0];//設(shè)置界面狀態(tài)
}
5.session后臺(tái)開啟任務(wù)
session后臺(tái)開啟任務(wù)的意義:
場(chǎng)景: APP下載一個(gè)比較大的文件侧巨,用戶開始下載后,讓APP進(jìn)入后臺(tái)鞭达,他去做別的事情司忱。
當(dāng)程序進(jìn)入后臺(tái)后皇忿,下載繼續(xù)進(jìn)行,下載完成后坦仍,用戶正常打開應(yīng)該為100%位置鳍烁。但是程序在后臺(tái)無(wú)法更新UI,此時(shí)可以通過(guò)應(yīng)用程序的代理進(jìn)行UI更新繁扎。
AppDelegate.m添加函數(shù)
/*
有其中幾個(gè)任務(wù)完成后幔荒,系統(tǒng)會(huì)調(diào)用此應(yīng)用程序的該方法
此方法會(huì)包含一個(gè)competionHandler,通常我們會(huì)保存此對(duì)象
competionHandler此操作表示應(yīng)用完成所有處理工作
**/
- (void)application:(UIApplication *)application
handleEventsForBackgroundURLSession:(NSString *)identifier
completionHandler:(void (^)())completionHandler
{
//backgroundSessionCompletionHandler是自定義的一個(gè)屬性
self.backgroundSessionCompletionHandler = completionHandler;
}
在實(shí)現(xiàn)NSURLSessionDelegate代理方法
/*
直到最后一個(gè)任務(wù)完成梳玫,系統(tǒng)會(huì)調(diào)用該方法爹梁。
在這個(gè)方法中通常可以進(jìn)行UI更新提澎,并調(diào)用completionHandler通知系統(tǒng)已經(jīng)完成所有操作姚垃。
*/
- (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session
{
AppDelegate *appDelegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
//這中間就可以寫更新UI的代碼了
if (appDelegate.backgroundSessionCompletionHandler) {
void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;
appDelegate.backgroundSessionCompletionHandler = nil;
completionHandler();
}
}
文章中有些內(nèi)容是引用了其他文章的內(nèi)容,時(shí)間久了虱朵,找不到具體的鏈接了莉炉,如有原文作者看到,請(qǐng)聯(lián)系我碴犬,我加上你原文地址絮宁,同時(shí)也感謝你寫的文章給了我很多的幫助。