USURLSession基本使用介紹

USURLSession基本使用介紹

在2013的WWDC上,蘋果推出了NSURLConnection的繼任者NSURLSession,并且在iOS9.0之后,以前使用的NSURLConnection將提示過期,推薦使用NSURLSession來替換NSURLConnection完成網(wǎng)路請求相關(guān)操作。與 NSURLConnection 一樣,NSURLSession 指的也不僅是同名類 NSURLSession,還包括一系列相互關(guān)聯(lián)的類。NSURLSession 包括了與之前相同的組件,NSURLRequest 與 NSURLCache,但是把 NSURLConnection 替換成了 NSURLSession、NSURLSessionConfiguration 以及 NSURLSessionTask 的 3 個子類:NSURLSessionDataTask,NSURLSessionUploadTask,NSURLSessionDownloadTask,這三個子類可以直接使用,每個任務(wù)都可以掛起(suspend),結(jié)束(cancel) 和 執(zhí)行(resume),調(diào)用響應(yīng)的函數(shù)即可
</br>
與 NSURLConnection 相比,NSURLsession 最直接的改進就是可以配置每個 session 的緩存,協(xié)議,cookie,以及證書策略(credential policy),甚至跨程序共享這些信息。這將允許程序和網(wǎng)絡(luò)基礎(chǔ)框架之間相互獨立,不會發(fā)生干擾。每個 NSURLSession 對象都由一個 NSURLSessionConfiguration 對象來進行初始化,后者指定了剛才提到的那些策略以及一些用來增強移動設(shè)備上性能的新選項。


1、NSURLSessionDataTask 獲取服務(wù)器上的數(shù)據(jù),返回相關(guān)數(shù)據(jù),獲取后直接處理
2、NSURLSessionUploadTask 創(chuàng)建一個上傳任務(wù),在上傳時需要制定文件源或數(shù)據(jù)源,一般來說,對于一個上傳任務(wù),也會收到服務(wù)的響應(yīng)也會有相關(guān)數(shù)據(jù)返回,所以NSURLSessionUploadTask繼承于NSURLSessionDataTask
3、NSURLSessionDownloadTask 下載服務(wù)器上的數(shù)據(jù),當(dāng)任務(wù)結(jié)束的時候,他會帶回一個下載文件的一個臨時文件路徑,所以在下載大容量任務(wù)時,使用尤為方便。
每一個task都是可以取消,暫停或者恢復(fù)的。當(dāng)一個 download task 取消時,可以通過選項來創(chuàng)建一個恢復(fù)數(shù)據(jù)(resume data),然后可以傳遞給下一次新創(chuàng)建的 download task,以便繼續(xù)之前的下載,這在斷點下載的時候尤為有用。

NSURLSession常用的類

1、NSURL:根據(jù)url生成的請求地址
2、NSURLRequest:封裝的一個請求,攜帶發(fā)送給服務(wù)器的全部數(shù)據(jù),里面包含一個NSURL對象,請求方法,請求頭,請求體等等。
3、NSMutableURLRequest:這個是NSURLRequest的子類,通過名字我們可以看出這是一個可變的對象,我們可以在這里自定義設(shè)置發(fā)送的服務(wù)器的全部數(shù)據(jù)(超市等待時間、請求方法、請求體、請求頭)
4、NSURLResponse:服務(wù)的響應(yīng)類,和NSURLRequest對象,包含服務(wù)返回的響應(yīng)頭部數(shù)據(jù)
5、NSURLSessionConfiguration 用于配置會話的屬性,可以通過該類配置會話的工作模式:
+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 工作模式類似于原來的NSURLConnection,可以使用緩存的Cache,Cookie,鑒權(quán)
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 不使用緩存的Cache,Cookie,鑒權(quán)。
+ (NSURLSessionConfiguration *)backgroundSessionConfiguration:(NSString *)identifier; 創(chuàng)建一個后臺 session,后臺 session 不同于常規(guī)的,普通的 session,它甚至可以在應(yīng)用程序掛起,退出或者崩潰的情況下運行上傳和下載任務(wù),創(chuàng)建Configuration對象的時候需要給一個NSString的ID用于用于標(biāo)記后臺的session。(稍后詳細(xì)描述)
6、NSURLSession:會話對象

NSURLSession的使用步驟

1、根據(jù)url創(chuàng)建一個NSURL對象
2、根據(jù)創(chuàng)建的NSURL創(chuàng)建一個NSURLRequest對象,創(chuàng)建請求對象(此對象內(nèi)容全部都是默認(rèn)值,如:請求方法默認(rèn)是GET),如果想要自定數(shù)據(jù)則創(chuàng)建NSMutableURLRequest對象
3、創(chuàng)建會話對象NSURLSession,創(chuàng)建NSURLSession對象有三種方法:

1)+ (NSURLSession *)sharedSession; 返回一個默認(rèn)的NSURLSession,使用共享的會話,該會話使用全局的Cache,Cookie和證書
2)+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration; 返回一個根據(jù)剛才創(chuàng)建的Configuration的NSURLSession對象,系統(tǒng)默認(rèn)創(chuàng)建一個新的OperationQueue處理Session的消息
3)+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue; 返回一個根據(jù)剛才創(chuàng)建的Configuration的NSURLSession對象,可以設(shè)定回調(diào)的delegate(注意這個回調(diào)delegate會被強引用),并且可以設(shè)定delegate在哪個OperationQueue回調(diào),如果我們將其設(shè)置為[NSOperationQueue mainQueue]就能在主線程進行回調(diào)非常的方便

4、使用創(chuàng)建好的NSURLSession對象和NSURLRequest對象創(chuàng)建一個NSURLSessionTask任務(wù),NSURLSessionDataTask、NSURLSessionUploadTask 或者 NSURLSessionDownloadTask
5、調(diào)用resume開始工作
6、當(dāng)不再需要連接調(diào)用Session的invalidateAndCancel直接關(guān)閉,或者調(diào)用finishTasksAndInvalidate等待當(dāng)前Task結(jié)束后關(guān)閉。這時Delegate會收到URLSession:didBecomeInvalidWithError:這個事件。Delegate收到這個事件之后會被解引用。
</br>
和NSURLConnection一樣,NSURLSession也提供了兩種形式的使用,代理模式和非代理模式

非代理模式

每個task的構(gòu)造方法都提供了一個–dataTaskWithRequest:completionHandler:的函數(shù),類似NSURLConnection的sendAsynchronousRequest:queue:completionHandler:sendSynchronousRequest:returningResponse:error:模式,只是NSURLSession僅有異步版本。
例如,如果創(chuàng)建一個NSURLSessionDataTask任務(wù):

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    NSURLSessionDataTask *task = [self.session dataTaskWithRequest:request
                                         completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         //接受的數(shù)據(jù)data、服務(wù)器響應(yīng)response、錯誤代碼error
     }];

    //啟動task
    [task resume];
    //其它方法,如取消任務(wù),暫停任務(wù)等
    //[task cancel];
    //[task suspend]

再者創(chuàng)建一個NSURLSessionUploadTask任務(wù)

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    NSData *data = ...; //上傳任務(wù)需要一個需要上傳的NSData對象或者一個本地文件路徑對應(yīng)的NSURL
    
    NSURLSessionDataTask *uploadTask = [self.session uploadTaskWithRequest:request
                                                            fromData:data
                                                   completionHandler:
     ^(NSData *data, NSURLResponse *response, NSError *error) {
         //接受的數(shù)據(jù)data、服務(wù)器響應(yīng)response、錯誤代碼error
     }];
     
    //啟動task
    [uploadTask resume];
    //其它方法,如取消任務(wù),暫停任務(wù)等
    //[uploadTask cancel];
    //[uploadTask suspend];

我們再來看看NSURLSessionDownloadTask任務(wù),下載任務(wù)的不同之處在于,NSURLSessionDownloadTask會一點一點的將下載數(shù)據(jù)寫入本地的臨時文件,回調(diào)block會帶回一個下載完成的臨時文件的地址,我們需要把文件從這個臨時地址移動到文件沙盒中保存起來使用。

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request
                                                         completionHandler:
    ^(NSURL *location, NSURLResponse *response, NSError *error) {
        //文件臨時地址location,服務(wù)器響應(yīng)response、錯誤代碼error
        //將臨時文件移動到app沙盒中
        NSString *documentsPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
        NSURL *documentsDirectoryURL = [NSURL fileURLWithPath:documentsPath];
        NSURL *newFileLocation = [documentsDirectoryURL URLByAppendingPathComponent:[[response URL] lastPathComponent]];
        [[NSFileManager defaultManager] copyItemAtURL:location toURL:newFileLocation error:nil];
    }];

    //啟動task
    [downloadTask resume];
    //其它方法,如取消任務(wù),暫停任務(wù)等
    //[downloadTask cancel];
    //[downloadTask suspend];

代理模式

NSURLSession有幾個代理協(xié)議NSURLSessionDelegate、NSURLSessionTaskDelegate、NSURLSessionDataDelegate、NSURLSessionDownloadDelegate這幾個協(xié)議個呈繼承關(guān)系,NSURLSessionTaskDelegate繼承NSURLSessionDelegate,NSURLSessionDataDelegate和NSURLSessionDownloadDelegate繼承自NSURLSessionTaskDelegate,實現(xiàn)不同的任務(wù),就實現(xiàn)相應(yīng)的協(xié)議。在這里我們以NSURLSessionDownloadDelegate協(xié)議為例:

    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
    self.session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[NSOperationQueue mainQueue]];
    NSString *imageURl = @"http://7xt5rm.com2.z0.glb.clouddn.com/picjumbo.com_download.jpg";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:imageURl]];
    
    //創(chuàng)建下載task
    NSURLSessionDownloadTask *downloadTask = [self.session downloadTaskWithRequest:request];
    
    //啟動task
    [downloadTask resume];
    //其它方法,如取消任務(wù),暫停任務(wù)等
    //[downloadTask cancel];
    //[downloadTask suspend];

代理方法,主要有這么幾個:

//當(dāng)接收到服務(wù)器響應(yīng)的時候調(diào)用
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
                                 didReceiveResponse:(NSURLResponse *)response
                                  completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler;

//下載完成之后調(diào)用該方法
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                              didFinishDownloadingToURL:(NSURL *)location;

//當(dāng)接收到下載數(shù)據(jù)的時候調(diào)用,可以在該方法中監(jiān)聽文件下載的進度該方法會被調(diào)用多次
//totalBytesWritten:已經(jīng)寫入到文件中的數(shù)據(jù)大小
//totalBytesExpectedToWrite:目前文件的總大小
//bytesWritten:本次下載的文件數(shù)據(jù)大小
//可以在此函數(shù)中計算下載進度
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                           didWriteData:(int64_t)bytesWritten
                                      totalBytesWritten:(int64_t)totalBytesWritten
                              totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;
//恢復(fù)下載的時候調(diào)用該方法
//fileOffset:恢復(fù)之后,要從文件的什么地方開發(fā)下載
//expectedTotalBytes:該文件數(shù)據(jù)的總大小
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask
                                      didResumeAtOffset:(int64_t)fileOffset
                                     expectedTotalBytes:(int64_t)expectedTotalBytes;

//當(dāng)請求完成之后調(diào)用該方法
//不論是請求成功還是請求失敗都調(diào)用該方法,如果請求失敗,那么error對象有值,否則那么error對象為空
//所有方法之中最后調(diào)用
-(void)URLSession:(nonnull NSURLSession *)session task:(nonnull NSURLSessionTask *)task didCompleteWithError:(nullable NSError *)error

和NSURLConnection一樣我們這里也介紹一下斷點下載的相關(guān)代碼

第一種:每一個task都是有三種狀態(tài)掛起、執(zhí)行和取消,所以我們可以在暫停時刻掛起任務(wù),重新下載時執(zhí)行任務(wù)即可
        if (downloadTask.state == NSURLSessionTaskStateSuspended) {
            [downloadTask resume];
        } else {
            [downloadTask suspend];
        }
     但是很多時候不是使用這種方法,不知有哪里不妥。。
第二種:取消的任務(wù)的時候保存已下載文件的信息,在恢復(fù)下載時,傳入此信息。
    //取消下載
    [downloadTask cancelByProducingResumeData:^(NSData * __nullable resumeData) {
        self.resumeData = resumeData;
    }];
    //恢復(fù)下載
    downloadTask = [self.session downloadTaskWithResumeData:self.resumeData];
    [downloadTask resume];
    比較常用的是這一種。。

后臺下載

前面講到我們可以通過設(shè)置NSURLSessionConfiguration的屬性BackgroundSession來實現(xiàn)后臺下載,在Task執(zhí)行的時候,用戶切到后臺,Session會和ApplicationDelegate做交互。當(dāng)程序切到后臺后,在BackgroundSession中的Task還會繼續(xù)下載。
在切到后臺之后,Session的Delegate不會再收到Task相關(guān)的消息,直到所有Task全都完成后,系統(tǒng)會調(diào)用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回調(diào),之后“匯報”下載工作,對于每一個后臺下載的Task調(diào)用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的話)和URLSession:task:didCompleteWithError:(成功或者失敗都會調(diào)用)之后調(diào)用Session的Delegate回調(diào)URLSessionDidFinishEventsForBackgroundURLSession:

看一下代碼:
在AppDelegate.m中,加入后臺處理函數(shù)

- (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier completionHandler:(void (^)())completionHandler{
    
    self.backgroundTransferCompletionHandler = completionHandler;
    
}

實現(xiàn)delegate的-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session方法

// 后臺傳輸完成,處理URLSession完成事件
-(void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session{
    AppDelegate *appDelegate = [UIApplication sharedApplication].delegate;
    
    //檢查一下是否所有的下載任務(wù)都已經(jīng)完成
    [self.session getTasksWithCompletionHandler:^(NSArray *dataTasks, NSArray *uploadTasks, NSArray *downloadTasks) {
        if ([uploadTasks count] == 0) {
            if (appDelegate.backgroundTransferCompletionHandler != nil) {
                //在ApplicationDelegate被喚醒后,會有個參數(shù)ComplietionHandler,這個參數(shù)是個Block,這個參數(shù)要在后面Session的Delegate中didFinish的時候調(diào)用一下
                
                void(^completionHandler)() = appDelegate.backgroundTransferCompletionHandler;
                appDelegate.backgroundTransferCompletionHandler = nil;
                completionHandler();
            }
        }    
        
    }];
    //執(zhí)行其他操作
    NSLog(@"All tasks are finished"); 
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

  • iOS開發(fā)系列--網(wǎng)絡(luò)開發(fā) 概覽 大部分應(yīng)用程序都或多或少會牽扯到網(wǎng)絡(luò)開發(fā),例如說新浪微博、微信等,這些應(yīng)用本身可...
    lichengjin閱讀 4,046評論 2 7
  • NSURLSession 使用步驟使用NSURLSession對象創(chuàng)建Task,然后執(zhí)行Task -(void)g...
    BEYOND黃閱讀 995評論 0 0
  • 在蘋果徹底棄用NSURLConnection之后自己總結(jié)的一個網(wǎng)上的內(nèi)容,加上自己寫的小Demo,很多都是借鑒網(wǎng)絡(luò)...
    付寒宇閱讀 4,530評論 2 13
  • 直接將view添加到Window上面,[[UIApplication sharedApplication].del...
    AnderQZ閱讀 225評論 0 0
  • 自習(xí)室告一段落后……………………曖昧 是一種微妙的感覺有所保留又有所突破我喜歡這種感覺我想永遠(yuǎn)保持這種感覺但世間之...
    純真閱讀 274評論 0 1

友情鏈接更多精彩內(nèi)容