為什么要使用NSURLSession?
翻譯原文 ,所有版權(quán)規(guī)其所有。
well,先來看一些優(yōu)點:
后臺上傳和下載:只需在創(chuàng)建NSURLSession的時候配置一個選項,就能得到后臺網(wǎng)絡(luò)的所有好處。這樣可以延長電池壽命,并且還支持UIKit的多task,在進(jìn)程間使用相同的委托模型。能夠暫停和恢復(fù)網(wǎng)絡(luò)操作:使用NSURLSession API能夠暫停,停止,恢復(fù)所有的網(wǎng)絡(luò)任務(wù),再也完全不需要子類化NSOperation.可配置的容器:對于NSURLSession里面的requests來說,每個NSURLSession都是可配置的容器。舉個例來說,假如你需要設(shè)置HTTP header選項,你只用做一次,session里面的每個request就會有同樣的配置。提高認(rèn)證處理:認(rèn)證是在一個指定的連接基礎(chǔ)上完成的。在使用NSURLConnection時,如果發(fā)出一個訪問,會返回一個任意的request。此時,你就不能確切的知道哪個request收到了訪問。而在NSURLSession中,就能用代理處理認(rèn)證。豐富的代理模式:在處理認(rèn)證的時候,NSURLConnection有一些基于異步的block方法,但是它的代理方法就不能處理認(rèn)證,不管請求是成功或是失敗。在NSURLSession中,可以混合使用代理和block方法處理認(rèn)證。上傳和下載通過文件系統(tǒng):它鼓勵將數(shù)據(jù)(文件內(nèi)容)從元數(shù)據(jù)(URL和settings)中分離出來。
NSURLSession vs NSURLConnection
“哇喔,看起來NSURLSession好復(fù)雜!”,你可能會這樣想。“還是堅持用NSURLConnection吧?!?/p>
別擔(dān)心 — 使用NSURLSession處理簡單task就如使用NSURLConnection一樣容易。例如,我們使用一個簡單的網(wǎng)絡(luò)調(diào)用,來得到倫敦最新天氣的JSON數(shù)據(jù)。
假設(shè)你有這樣一個URL字符串:
NSString *londonWeatherUrl = @"http://api.openweathermap.org/data/2.5/weather?q=London,uk" ;
首先,使用NSURLConnection會這么做:
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:londonWeatherUrl]];
[NSURLConnection sendAsynchronousRequest:request queue:[NSOperationQueue mainQueue] completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *connectionError) {
// handle response
}];
那來看下NSURLSession是怎么做的。這個是NSURLSession使用的最簡單方法。隨后你還會看到怎樣配置session,設(shè)置其他的特性,比如代理。
NSURLSession *session = [NSURLSession sharedSession];
[[session dataTaskWithURL:[NSURL URLWithString:londonWeatherUrl]
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle response
}] resume];
注意,你不需要指定運行哪個隊列,默認(rèn)會開辟一個后臺線程。如果有兩個的話,這種設(shè)計可能就比較難區(qū)分之間的不同。蘋果官方旨在使用dataTaskWithURL來代替NSURLConnection中的sendAsynchronousRequest。
看吧,NSURLSession就如NSURLConnection一樣易用,并且還有一些額外的功能。
NSURLSession vs AFNetworking
說到網(wǎng)絡(luò)請求不得不說的就是AFNetworking Framework。這是iOS/OS X上最流行的框架之一,由Mattt Thompson創(chuàng)建。
<pre>
<b>注意</b>:學(xué)習(xí)AFNetworking,可以在github頁面上找到,<a harf="https://github.com/AFNetworking/AFNetworking">https://github.com/AFNetworking/AFNetworking</a>,你還可以看這篇教程<a harf="http://www.raywenderlich.com/30445/afnetworking-crash-course">http://www.raywenderlich.com/30445/afnetworking-crash-course</a>
</pre>
下面是對于同樣的數(shù)據(jù)請求,AFNetworking 1.x的代碼:
NSURLRequest *request = [NSURLRequest requestWithURL:
[NSURL URLWithString:londonWeatherUrl]];
AFJSONRequestOperation *operation =
[AFJSONRequestOperation JSONRequestOperationWithRequest:request
success:^(NSURLRequest *request,
NSHTTPURLResponse *response,
id JSON) {
// handle response
} failure:nil];
[operation start];
使用AFNetworking的好處之一是,它的處理響應(yīng)數(shù)據(jù)是數(shù)據(jù)類型類,AFJSONRequestOperation(或類似XML,plist)的返回成功的block里面已經(jīng)解析出了你要的數(shù)據(jù)。而NSURLSession接收到的是NSData類型,你需要把它再轉(zhuǎn)換成JSON類型。
<pre>
<b>注意:</b>用NSJSONSerialization可以輕松的將NSData類型轉(zhuǎn)換為JSON類型。
</pre>
那么,你是喜歡用AFNetworking還是NSURLSession呢?
個人認(rèn)為,簡單的需求最好用NSURlSession-這可減少工程里面第三方庫的依賴。當(dāng)然了,現(xiàn)在AFNetworking也添加了新的代理,配置,基于task的API等等特性。
如果你使用了AFNetworking2.0的新特性,比如系列化,并且還集成了UIKit(加入了一些UIImageView的類目方法),現(xiàn)在就很難說服你不用它了。
<pre>
<b>注意:</b>在AFNetworking2.0的分支,他們已經(jīng)轉(zhuǎn)成使用NSURLSession。
<a harf="https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide">https://github.com/AFNetworking/AFNetworking/wiki/AFNetworking-2.0-Migration-Guide</a>
</pre>
譯者注:中間這里有一部分講到了Dropbox,這里就不翻譯了。對于Dropbox,國內(nèi)墻得厲害,完全打不開。
NSURLSession 類套(suite of classes)
蘋果公司描述了新類NSURLSession,及其類套。包括新的上傳,下載,處理認(rèn)證等工具,能處理http協(xié)議中的所用事情。
在編碼前,重要的先理解它們是怎樣協(xié)同工作的。

NSurLSession由NSuRLSessionConfiguration和可選代理(optional delegate)構(gòu)成。再根據(jù)你的網(wǎng)絡(luò)需求通過NSURLSessionTask來創(chuàng)建session。
NSURLSessionConfiguration
有三個方法用來創(chuàng)建NSURLSessionConfiguration:
defaultSessionConfiguration- 使用全局的cache,cookie和credential storage objects來創(chuàng)建configuration對象。
ephemeralSessionConfiguration – 這個configuration用于“private” sessions,還有對于cache, cookie, or credential storage objects的非永久存儲。
backgroundSessionConfiguration – 做遠(yuǎn)程push通知或是應(yīng)用程序掛起的時候就要用到這個configuration。
一旦創(chuàng)建了NSURLSessionConfiguration就可以給它設(shè)置各種屬性:
NSURLSessionConfiguration *sessionConfig =
[NSURLSessionConfiguration defaultSessionConfiguration];
// 1
sessionConfig.allowsCellularAccess = NO;
// 2
[sessionConfig setHTTPAdditionalHeaders:
@{@"Accept": @"application/json"}];
// 3
sessionConfig.timeoutIntervalForRequest = 30.0;
sessionConfig.timeoutIntervalForResource = 60.0;
sessionConfig.HTTPMaximumConnectionsPerHost = 1;
- 限制了網(wǎng)絡(luò)只能是wifi。
- 設(shè)置了所有的請求只接收J(rèn)SON數(shù)據(jù)
- 配置網(wǎng)絡(luò)超時,限制一個主機只有一個網(wǎng)絡(luò)連接。
這里僅僅只做了一些簡單的配置,看文檔去了解更多的屬性吧。
NSURLSession
NSURLSession是為了代替NSURLConnection而設(shè)計的。Sessions的所有工作都是通過它的小弟,也就是NSURLSessionTask的對象??梢杂胋lock,delegate,或者兩者混合來創(chuàng)建task。舉個例子,你要下載圖片,就要創(chuàng)建NSURLSessionDownloadTask。
首先需要創(chuàng)建session:
// 1
NSString *imageUrl =
@"http://www.raywenderlich.com/images/store/ iOS7_PDFonly_280@2x_authorTBA.png";
// 2
NSURLSessionConfiguration *sessionConfig =[NSURLSessionConfiguration defaultSessionConfiguration];
// 3
NSURLSession *session =[NSURLSession sessionWithConfiguration:sessionConfig
delegate:self
delegateQueue:nil];
ok,這個看上去和前面的只有點不同,一步一步看:
- 這里下載一張圖片(譯者改:原文匪夷所思)。
- 創(chuàng)建NSURLConfiguration。
- 用當(dāng)前類對象作為代理創(chuàng)建session。
之后,通過創(chuàng)建帶有完成處理的task來下載圖片:
// 1
NSURLSessionDownloadTask *getImageTask =
[session downloadTaskWithURL:[NSURL URLWithString:imageUrl]
completionHandler:^(NSURL *location,
NSURLResponse *response,
NSError *error) {
// 2
UIImage *downloadedImage =
[UIImage imageWithData:
[NSData dataWithContentsOfURL:location]];
//3
dispatch_async(dispatch_get_main_queue(), ^{
// do stuff with image
_imageWithBlock.image = downloadedImage;
});
}];
// 4
[getImageTask resume];
很好,現(xiàn)在看起來像網(wǎng)絡(luò)請求代碼了!
-
task由session創(chuàng)建。上面是創(chuàng)建了一個基于block的方法。你還可以用NSURLSessionDownloadDelegate跟蹤下載進(jìn)度:
-URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 通過location變量來得到image指針。
然后是更新UIImageView的圖片。
開始這個task。
session能夠輕松的創(chuàng)建task,并發(fā)送到代理方法,通知你完成。
這是像上面使用相同的session:
// 1
NSURLSessionDownloadTask *getImageTask = [session downloadTaskWithURL:[NSURL URLWithString:imageUrl]];
[getImageTask resume];
-
如果你接下來什么都不做的話,我們就使用這些代碼。那么,就需要實現(xiàn)這個協(xié)議中的代理方法NSURLSessionDownloadDelegate。首先是,收到下載完成的通知:
-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location { // use code above from completion handler }
這里再一次給你提供了location,然后用它就能獲取image。
最后,如果需要跟蹤下載進(jìn)度:
-(void)URLSession:(NSURLSession *)session
downloadTask:(NSURLSessionDownloadTask *)downloadTask
didWriteData:(int64_t)bytesWritten
totalBytesWritten:(int64_t)totalBytesWritten
totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite
{
NSLog(@"%f / %f", (double)totalBytesWritten,
(double)totalBytesExpectedToWrite);
}
NSURLSessionTask
上面看了NSURLSessionDataTask和NSURLSessionDownloadTask的使用。這兩個都是繼承至NSURLSessionTask:

NSURLSessionTask是session中task的基類,它們只能由session或session的子類創(chuàng)建。
NSURLSessionDataTask
這個task調(diào)用HTTP GET請求從服務(wù)器獲取數(shù)據(jù)。返回的數(shù)據(jù)格式是NSData。可能需要你自己轉(zhuǎn)換成XML,JSON,UIimage等..
NSURLSessionDataTask *jsonData = [session dataTaskWithURL:yourNSURL
completionHandler:^(NSData *data,
NSURLResponse *response,
NSError *error) {
// handle NSData
}];
NSURLSessionUploadTask
這個類是上傳用的,在數(shù)據(jù)傳輸過程中,這個代理方法能觀察網(wǎng)絡(luò)狀況。
上傳一張圖片:
NSData *imageData = UIImageJPEGRepresentation(image, 0.6);
NSURLSessionUploadTask *uploadTask = [upLoadSession uploadTaskWithRequest:request fromData:imageData];
這個task由session創(chuàng)建,上傳圖片的NSData。其他上傳方法還有上傳文件,或是數(shù)據(jù)流。
NSURLSessionDownloadTask
NSURLSessionDownloadTask下載文件更簡單,可以在下載中掛起,恢復(fù)。它有一點點不同于其他兩個子類。
- task的類型直接寫到一個臨時文件中。
- 下載過程中會調(diào)用
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:去更新狀態(tài)。 - 當(dāng)task完成,
URLSession:downloadTask:didFinishDownloadingToURL:會被調(diào)用。此時你可以將臨時文件保存到永久文件中。 - 下載失敗或是取消還可以得到已經(jīng)下載的那一部分?jǐn)?shù)據(jù)。
使用這個掛起task:
//[uploadTask resume];
[uploadTask suspend];
同時管理多個task時,可以用taskIdentifier屬性來唯一標(biāo)識task。
well,現(xiàn)在了解了NSURLSession類套中主要的類。
后面還有一部分,還是與Dropbox有關(guān)的,就不再翻譯了。
轉(zhuǎn)載請注明出處。