NSURLSession概述1. NSURLSession session類型NSURLSession包括下面3種session類型a). Default session(默認(rèn)會(huì)話模式):使用的是基于磁盤緩存的持久化策略,工作模式類似于原來(lái)的NSURLConnection崔拥,可以用來(lái)取代NSURLConnection中的:[NSURLConnection sendAsynchronousRequest:queue:completionHandler:]b). Ephemeral session(瞬時(shí)會(huì)話模式):臨時(shí)的進(jìn)程內(nèi)會(huì)話(內(nèi)存)迅皇,不會(huì)將cookie宋税、證書券膀、緩存儲(chǔ)存到本地,只會(huì)放到內(nèi)存中既们,當(dāng)應(yīng)用程序退出后數(shù)據(jù)也會(huì)消失兢哭。c). Background session(后臺(tái)會(huì)話模式):和默認(rèn)會(huì)話模式類似, 不過(guò)相比默認(rèn)模式,該會(huì)話會(huì)在后臺(tái)開(kāi)啟一個(gè)線程進(jìn)行網(wǎng)絡(luò)數(shù)據(jù)處理四敞。//Default session+ (NSURLSessionConfiguration *)defaultSessionConfiguration;//Ephemeral+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;//Background + (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier;你需要了解包括NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 個(gè)子類:NSURLSessionDataTask拔妥,NSURLSessionUploadTask忿危,NSURLSessionDownloadTask。與 NSURLConnection 相比没龙,NSURLsession 最直接的改進(jìn)就是可以配置每個(gè) session 的緩存铺厨,協(xié)議,cookie硬纤,以及證書策略努释,甚至跨程序共享這些信息。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨(dú)立咬摇,不會(huì)發(fā)生干擾伐蒂。每個(gè) NSURLSession 對(duì)象都由一個(gè) NSURLSessionConfiguration 對(duì)象來(lái)進(jìn)行初始化。NSURLSession 中另一大塊就是 session task肛鹏。它負(fù)責(zé)處理數(shù)據(jù)的加載以及文件和數(shù)據(jù)在客戶端與服務(wù)端之間的上傳和下載逸邦。NSURLSessionTask 與 NSURLConnection 最大的相似之處在于它也負(fù)責(zé)數(shù)據(jù)的加載,最大的不同之處在于所有的 task 共享其創(chuàng)造者 NSURLSession 這一公共委托者(common delegate)在扰。2.NSURLSessionTask類NSURLSessionTask是一個(gè)抽象子類缕减,它有三個(gè)子類:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask芒珠。這三個(gè)類封裝了現(xiàn)代應(yīng)用程序的三個(gè)基本網(wǎng)絡(luò)任務(wù):獲取數(shù)據(jù)桥狡,比如JSON或XML,以及上傳和下載文件皱卓。下面是其繼承關(guān)系:不同于直接使用 alloc-init 初始化方法裹芝,task 是由一個(gè) NSURLSession 創(chuàng)建的。每個(gè) task 的構(gòu)造方法都對(duì)應(yīng)有或者沒(méi)有 completionHandler 這個(gè) block 的兩個(gè)版本娜汁。1).NSURLSessionDataTaskNSURLSessionDataTask使用NSData來(lái)交換數(shù)據(jù). NSURLSessionDataTask不支持后臺(tái)會(huì)話模式嫂易。a) 通過(guò)request對(duì)象或url創(chuàng)建//通過(guò)一個(gè)給定的請(qǐng)求- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;//通過(guò)一個(gè)給定的URL.- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;代理方法:- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTaskdidReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler{? ? completionHandler(NSURLSessionResponseAllow);}- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask? ? didReceiveData:(NSData *)data{? ? //data: response from the server.}b).通過(guò)request對(duì)象或url創(chuàng)建,同時(shí)指定任務(wù)完成后通過(guò)completionHandler指定回調(diào)的代碼塊:- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;2).NSURLSessionDownloadTaska).通過(guò)URL/request/resumeData創(chuàng)建- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;//下載任務(wù)支持?jǐn)帱c(diǎn)續(xù)傳掐禁,這種方式是通過(guò)之前已經(jīng)下載的數(shù)據(jù)來(lái)創(chuàng)建下載任務(wù)怜械。- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;代理方法:- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask? ? ? ? ? ? ? ? ? ? ? ? ? ? ? didFinishDownloadingToURL:(NSURL *)location;- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? didWriteData:(int64_t)bytesWritten? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? totalBytesWritten:(int64_t)totalBytesWritten? ? ? ? ? ? ? ? ? ? ? ? ? ? ? totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? didResumeAtOffset:(int64_t)fileOffset? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? expectedTotalBytes:(int64_t)expectedTotalBytes;b).通過(guò)completionHandler指定任務(wù)完成后的回調(diào)代碼塊:- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData completionHandler:(void (^)(NSURL *location, NSURLResponse *response, NSError *error))completionHandler;3).NSURLSessionUploadTaska).通過(guò)request創(chuàng)建,在上傳時(shí)指定文件源或數(shù)據(jù)源傅事。- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;代理方法:- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? didSendBodyData:(int64_t)bytesSent? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? totalBytesSent:(int64_t)totalBytesSent? ? ? ? ? ? ? ? ? ? ? totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend;b).通過(guò)completionHandler指定任務(wù)完成后的回調(diào)代碼塊- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData completionHandler:(void (^)(NSData *data, NSURLResponse *response, NSError *error))completionHandler;3.NSURLSession類從上面我們已經(jīng)知道創(chuàng)建一個(gè)NSURLSessionTask需要NSURLSession缕允,獲取NSURLSession類對(duì)象有幾種方式://使用全局的Cache,Cookie和證書蹭越。+ (NSURLSession *)sharedSession;? //創(chuàng)建對(duì)應(yīng)配置的會(huì)話障本。? + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;? + (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(id)delegate delegateQueue:(NSOperationQueue *)queue;第三種方式指定了session的委托和委托所處的隊(duì)列。當(dāng)不再需要連接時(shí)般又,可以調(diào)用Session的invalidateAndCancel直接關(guān)閉彼绷,或者調(diào)用finishTasksAndInvalidate等待當(dāng)前Task結(jié)束后關(guān)閉巍佑。這時(shí)Delegate會(huì)收到URLSession:didBecomeInvalidWithError:這個(gè)事件。Delegate收到這個(gè)事件之后會(huì)被解引用寄悯。3.NSURLSessionConfiguration類上面2萤衰、3種創(chuàng)建方式使用了NSURLSessionConfiguration,它用于配置會(huì)話的屬性猜旬,創(chuàng)建方法如下:+ (NSURLSessionConfiguration *)defaultSessionConfiguration;? + (NSURLSessionConfiguration *)ephemeralSessionConfiguration;? //identifier參數(shù)指定了會(huì)話的ID脆栋,用于標(biāo)記后臺(tái)的session。+ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier;這個(gè)類有兩個(gè)屬性:@property BOOL allowsCellularAccess;? @property (getter=isDiscretionary) BOOL discretionary NS_AVAILABLE(NA, 7_0);allowsCellularAccess 屬性指定是否允許使用蜂窩連接洒擦, discretionary屬性為YES時(shí)表示當(dāng)程序在后臺(tái)運(yùn)作時(shí)由系統(tǒng)自己選擇最佳的網(wǎng)絡(luò)連接配置椿争,該屬性可以節(jié)省通過(guò)蜂窩連接的帶寬。在使用后臺(tái)傳輸數(shù)據(jù)的時(shí)候熟嫩,建議使用discretionary屬性秦踪,而不是allowsCellularAccess屬性,因?yàn)樗鼤?huì)把WiFi和電源可用性考慮在內(nèi)掸茅。2.實(shí)例創(chuàng)建一個(gè)NSURLSession任務(wù)需要遵循以下步驟:a)創(chuàng)建一個(gè)Session Configurationb)創(chuàng)建一個(gè)NSURLSessionc) 創(chuàng)建一個(gè)NSURLSession Task ( Data,Download or Upload)d)代理方法e)調(diào)用resume方法1.數(shù)據(jù)請(qǐng)求前面通過(guò)請(qǐng)求一個(gè)NSURLSessionDataTask進(jìn)行數(shù)據(jù)請(qǐng)求演示:- (IBAction)loadData:(UIButton *)sender {? ? // 創(chuàng)建Data Task椅邓,? ? NSURL *url = [NSURL URLWithString:@"http://www.reibang.com/users/9tsPFp/latest_articles"];? ? NSURLRequest *request = [NSURLRequest requestWithURL:url];? ? NSURLSession *session = [NSURLSession sharedSession];? ? NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ^(NSData *data, NSURLResponse *response, NSError *error) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? // 輸出返回的狀態(tài)碼,請(qǐng)求成功的話為200? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if (!error) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? [self showResponseCode:response];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }else{? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"error is :%@",error.localizedDescription);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];? ? // 使用resume方法啟動(dòng)任務(wù)? ? [dataTask resume];}- (void)showResponseCode:(NSURLResponse *)response {? ? NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;? ? NSInteger responseStatusCode = [httpResponse statusCode];? ? NSLog(@"狀態(tài)碼--%ld", (long)responseStatusCode);}2.HTTP GET和POST1).GET我們使用豆瓣的API來(lái)演示這個(gè)GET請(qǐng)求- (IBAction)GETRequest:(id)sender {? ? NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];? ? NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: self delegateQueue: [NSOperationQueue mainQueue]];? ? NSURL * url = [NSURL URLWithString:@"https://api.douban.com/v2/book/1220562"];? ? NSURLSessionDataTask * dataTask = [delegateFreeSession dataTaskWithURL:url? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(error == nil)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"GET請(qǐng)求數(shù)據(jù)= %@",text);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];? ? [dataTask resume];}數(shù)據(jù)請(qǐng)求結(jié)果如下:2).POST我們使用http://hayageek.com/examples/jquery/ajax-post/ajax-post.php 這個(gè)接口來(lái)演示POST請(qǐng)求昧狮,POST需要4個(gè)參數(shù): name, loc, age, submit景馁,如下:- (IBAction)POSTRequest:(UIButton *)sender {? ? NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];? ? NSURLSession *delegateFreeSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate: nil delegateQueue: [NSOperationQueue mainQueue]];? ? NSURL * url = [NSURL URLWithString:@"http://hayageek.com/examples/jquery/ajax-post/ajax-post.php"];? ? NSMutableURLRequest * urlRequest = [NSMutableURLRequest requestWithURL:url];? ? NSString * params =@"name=Ravi&loc=India&age=31&submit=true";? ? [urlRequest setHTTPMethod:@"POST"];? ? [urlRequest setHTTPBody:[params dataUsingEncoding:NSUTF8StringEncoding]];? ? NSURLSessionDataTask * dataTask =[delegateFreeSession dataTaskWithRequest:urlRequest? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"Response:%@ %@\n", response, error);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? if(error == nil)? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? {? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSString * text = [[NSString alloc] initWithData: data encoding: NSUTF8StringEncoding];? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? NSLog(@"POST返回?cái)?shù)據(jù) = %@",text);? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? }];? ? [dataTask resume];}返回?cái)?shù)據(jù):Response:{ URL: http://hayageek.com/examples/jquery/ajax-post/ajax-post.php } { status code: 200, headers {? ? Connection = "keep-alive";? ? "Content-Encoding" = gzip;? ? "Content-Type" = "text/html";? ? Date = "Wed, 18 Mar 2015 01:43:07 GMT";? ? Server = nginx;? ? "Transfer-Encoding" = Identity;? ? Vary = "Accept-Encoding, Accept-Encoding";? ? "X-Powered-By" = "EasyEngine 2.0.0";} } (null)2015-03-18 09:43:10.418 WebConnectionDemo[28129:2666176] POST返回?cái)?shù)據(jù) = Data from server: {"name":"Ravi","loc":"India","age":"31","submit":"true"}
3.NSURLSessionUploadTaskUpload task 的創(chuàng)建需要使用一個(gè) request,另外加上一個(gè)要上傳的 NSData 對(duì)象或者是一個(gè)本地文件的路徑對(duì)應(yīng)的 NSURL逗鸣,類似的代碼如下:NSURL *URL = [NSURL URLWithString:@"http://example.com/upload"]; NSURLRequest *request = [NSURLRequest requestWithURL:URL]; NSData *data = ...; NSURLSession *session = [NSURLSession sharedSession]; NSURLSessionUploadTask *uploadTask = [session uploadTaskWithRequest:request? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? fromData:data? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? completionHandler:? ? ^(NSData *data, NSURLResponse *response, NSError *error) {? ? ? ? // ...? ? }]; [uploadTask resume];4.NSURLSessionDownloadTaska.普通下載- (IBAction)download:(id)sender {? ? NSURL * url = [NSURL URLWithString:@"http://e.hiphotos.baidu.com/image/pic/item/63d0f703918fa0ec14b94082249759ee3c6ddbc6.jpg"];? ? NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];? ? NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];? ? NSURLSessionDownloadTask * downloadTask =[ defaultSession downloadTaskWithURL:url];? ? [downloadTask resume];}為了實(shí)現(xiàn)下載進(jìn)度的顯示合住,需要在委托中的以下方法中實(shí)現(xiàn):-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite{? ? float progress = totalBytesWritten*1.0/totalBytesExpectedToWrite;? ? dispatch_async(dispatch_get_main_queue(),^ {? ? ? ? [self.process setProgress:progress animated:YES];? ? });? ? NSLog(@"Progress =%f",progress);? ? NSLog(@"Received: %lld bytes (Downloaded: %lld bytes)? Expected: %lld bytes.\n",? ? ? ? ? bytesWritten, totalBytesWritten, totalBytesExpectedToWrite);}Download task 是將數(shù)據(jù)一點(diǎn)點(diǎn)地寫入本地的臨時(shí)文件。我們需要把文件從一個(gè)臨時(shí)地址移動(dòng)到一個(gè)永久的地址保存起來(lái)::-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{? ? NSLog(@"Temporary File :%@\n", location);? ? NSError *err = nil;? ? NSFileManager *fileManager = [NSFileManager defaultManager];? ? NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];? ? NSURL *docsDirURL = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent:@"out1.zip"]];? ? if ([fileManager moveItemAtURL:location? ? ? ? ? ? ? ? ? ? ? ? ? ? toURL:docsDirURL? ? ? ? ? ? ? ? ? ? ? ? ? ? error: &err])? ? {? ? ? ? NSLog(@"File is saved to =%@",docsDir);? ? }? ? else? ? {? ? ? ? NSLog(@"failed to move: %@",[err userInfo]);? ? }}如下所示:b.可取消的下載我們將做一些改動(dòng)撒璧,使其支持取消下載透葛,先創(chuàng)建一個(gè)全局NSURLSessionDownloadTask對(duì)象:@property (strong, nonatomic) NSURLSessionDownloadTask *cancellableTask;調(diào)用cancle方法即可取消:- (IBAction)cancleDownload:(UIButton *)sender {? ? if (self.cancellableTask) {? ? ? ? [self.cancellableTask cancel];? ? ? ? self.cancellableTask = nil;? ? }}這樣點(diǎn)擊cancle按鈕后下載任務(wù)會(huì)取消,重新點(diǎn)擊下載會(huì)從最初的經(jīng)度條開(kāi)始下載沪悲。c.斷點(diǎn)續(xù)傳下載斷點(diǎn)續(xù)傳获洲,我們需要一個(gè)NSData來(lái)暫存我們下載的數(shù)據(jù):@property (strong, nonatomic) NSData *partialData;download方法中做以下改動(dòng),如果已經(jīng)有緩存的數(shù)據(jù)殿如,即使用downloadTaskWithResumeData進(jìn)行下載:- (IBAction)download:(UIButton *)sender {? ? NSURLSessionConfiguration *defaultConfigObject = [NSURLSessionConfiguration defaultSessionConfiguration];? ? NSURLSession *defaultSession = [NSURLSession sessionWithConfiguration: defaultConfigObject delegate:self delegateQueue: [NSOperationQueue mainQueue]];? ? if (self.partialData) {? ? ? ? self.cancellableTask = [defaultSession downloadTaskWithResumeData:self.partialData];? ? }? ? else{? ? NSURL * url = [NSURL URLWithString:@"http://e.hiphotos.baidu.com/image/pic/item/63d0f703918fa0ec14b94082249759ee3c6ddbc6.jpg"];? ? self.cancellableTask =[ defaultSession downloadTaskWithURL:url];? ? }? ? [self.cancellableTask resume];}cancle方法也需要做改動(dòng),我們需要保存我們已下載的數(shù)據(jù):- (IBAction)cancleDownload:(UIButton *)sender {? ? if (self.cancellableTask) {? ? ? ? [self.cancellableTask cancelByProducingResumeData:^(NSData *resumeData) {? ? ? ? ? ? self.partialData = resumeData;? ? ? ? }];? ? ? ? self.cancellableTask = nil;? ? }}另外恢復(fù)下載時(shí)最爬,NSURLSessionDownloadDelegate中的以下方法將被調(diào)用:-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didResumeAtOffset:(int64_t)fileOffset expectedTotalBytes:(int64_t)expectedTotalBytes{? ? NSLog(@"NSURLSessionDownloadDelegate: Resume download at %lld", fileOffset);}如下:6.后臺(tái)下載首先創(chuàng)建一個(gè)全局對(duì)象:@property (strong, nonatomic) NSURLSessionDownloadTask * backgroundDownloadTask;配置下載任務(wù):- (IBAction)downoadBackground:(id)sender {? ? NSURL * url = [NSURL URLWithString:@"https://developer.apple.com/library/ios/documentation/General/Conceptual/CocoaEncyclopedia/CocoaEncyclopedia.pdf"];? ? NSURLSessionConfiguration * backgroundConfig = [NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"backgroundtask1"];? ? NSURLSession *backgroundSeesion = [NSURLSession sessionWithConfiguration: backgroundConfig delegate:self delegateQueue: [NSOperationQueue mainQueue]];? ? self.backgroundDownloadTask =[ backgroundSeesion downloadTaskWithURL:url];? ? [self.backgroundDownloadTask resume];}在程序進(jìn)入后臺(tái)后涉馁,如果下載任務(wù)完成,AppDelegate中的對(duì)應(yīng)方法將被調(diào)用:- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{? ? NSLog(@"Save completionHandler");? ? self.completionHandler = completionHandler;}然后修改上面那個(gè)協(xié)議方法爱致,如下:-(void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location{? ? if (downloadTask == self.cancellableTask) {? ? ? ? NSLog(@"Temporary File :%@\n", location);? ? ? ? NSError *err = nil;? ? ? ? NSFileManager *fileManager = [NSFileManager defaultManager];? ? ? ? NSString *docsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];? ? ? ? NSURL *docsDirURL = [NSURL fileURLWithPath:[docsDir stringByAppendingPathComponent:@"out1.zip"]];? ? ? ? if ([fileManager moveItemAtURL:location? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? toURL:docsDirURL? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? error: &err]){? ? ? ? ? ? NSLog(@"File is saved to =%@",docsDir);? ? ? ? }? ? ? ? else{? ? ? ? ? ? NSLog(@"failed to move: %@",[err userInfo]);? ? ? ? }? ? }else if(downloadTask == self.backgroundDownloadTask){? ? ? ? NSLog(@"Background URL session %@ finished events.\n", session);? ? ? ? AppDelegate * delegate =(AppDelegate *)[[UIApplication sharedApplication] delegate];? ? ? ? if(delegate.completionHandler)? ? ? ? {? ? ? ? ? ? void (^handler)() = delegate.completionHandler;? ? ? ? ? ? handler();? ? ? ? }? ? }}運(yùn)行程序并退出當(dāng)前程序后打印結(jié)果如下:Received: 21127 bytes (Downloaded: 1439932 bytes)? Expected: 1464162 bytes.Progress =0.997860Received: 21096 bytes (Downloaded: 1461028 bytes)? Expected: 1464162 bytes.Progress =1.000000Received: 3134 bytes (Downloaded: 1464162 bytes)? Expected: 1464162 bytes.Background URL session <__NSURLBackgroundSession: 0x7fc5c357b560> finished events.關(guān)于NSURLSessionConfiguration的配置策略你可以在這篇文章中找到烤送,下一節(jié)我們講AFNetworking和WebView。