玩轉 iOS 開發:NSURLSession 講解 (一)

CainLuo發表於2017-06-22

文章分享至我的個人技術部落格: https://cainluo.github.io/14980521480137.html


NSURLSession

在2013年的時候, 蘋果推出了iOS 7, 這個版本的iOS被稱為革命性的iOS, 而我們以前所用到的NSURLConnection這個網路庫也被蘋果爸爸給重構, 並且重新命名為NSURLSession.

現在在GitHub裡用的最多的兩個庫AFNetworking, SDWebImage都是用了NSURLSession.

這裡就不廢話了, 直接來知識點吧.


網路通訊

關於Session的意思, 我這裡找到一段比較古方的解釋:

Session翻譯為中文意思是會話,我們知道,在七層網路協議中有物理層->資料鏈路層->網路層->傳輸層->會話層->表示層->應用層,那我們可以將NSURLSession類理解為會話層,用於管理網路介面的建立、維護、刪除等等工作,我們要做的工作也只是會話層之後的層即可,底層的工作NSURLSession已經幫我們封裝好了.

看到這我們就很激動, 因為底層的東西不需要我們去管理, 這就輕鬆多了.


NSURLSession的分支

我們都知道蘋果爸爸用NSURLSession代替了NSURLConnection, 那麼NSURLSession裡面到底有什麼呢?

NSURLSession父類:

  • NSURLSession
  • NSURLSessionConfiguration

NSURLSessionTask子類:

  • NSURLSessionDataTask
  • NSURLSessionUploadTask
  • NSURLSessionDownloadTask
  • NSURLSessionStreamTask (iOS 9後才支援)

他們的主要關係:

1

NSURLSessionTask子類的繼承關係:

2

NSURLSessionDataTask: 主要使用在請求一些比較簡單的資料, 比如我們常用的JSON資料.

NSURLSessionDownloadTask: 這個主要使用在進行一些檔案的下載, 它可以針對一些大檔案的網路請求做更多的處理, 比如獲取下載進度, 檔案的斷點續傳等等牛逼事情.

NSURLSessionUploadTask: 這個和上面那個task對應, 主要是給伺服器傳送檔案資料所使用的.

NSURLSessionStreamTask: 提供TCP/IP的一個連結入口, 方便進行傳輸.


使用NSURLSession

不要以為看完了上面就可以直接拿來和伺服器互動了啦, 因為NSURLSession本身是不會進行請求, 需要通過建立對應的task, 然後配置完之後, 再去呼叫resume()方法才能夠進行tongxin.

這裡有一個好訊息就是同意個NSURLSession是可以建立多個task, 並且這些taskcachecookie都是共享的.

使用NSURLSession的步驟:

  1. 建立NSURLSession物件
  2. 使用NSURLSession建立對應的task
  3. 最後一步就是呼叫resume()方法, 開始請求.

建立NSURLSession物件有三種方法, 這裡就不建立工程裡, 直接貼程式碼吧:

第一種:

// 獲取一個共享的單例會話物件
    NSURLSession *urlSession = [NSURLSession sharedSession];
複製程式碼

第二種:

// 用NSURLSessionConfiguration獲取一個特定的NSURLSession
NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:<#(nonnull NSURLSessionConfiguration *)#>];
複製程式碼

第三種:

// 用NSURLSessionConfiguration獲取一個特定的NSURLSession, 並且設定好代理物件, 和代理的佇列
    NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:<#(nonnull NSURLSessionConfiguration *)#>
                                                             delegate:<#(nullable id<NSURLSessionDelegate>)#>
                                                        delegateQueue:<#(nullable NSOperationQueue *)#>]

複製程式碼

配置NSURLSession

剛剛我們也提到, NSURLSession是沒法直接進行請求的, 所以我們需要去配置一下, 這裡也有三種配置的方法.

第一種:

// NSURLSessionConfiguration的預設配置, 這種配置會把快取資料儲存到磁碟上
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;

NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]];
複製程式碼

第二種:

// NSURLSessionConfiguration的第二種配置, 這種配置不會把資料持久化, 也就是說不會儲存到磁碟上
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;

NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration ephemeralSessionConfiguration]];
複製程式碼

第三種:

// 這個配置可以允許程式在後臺進行上傳和下載的操作, 給定一個Identifier可以在系統關閉應用之後重啟, 根據給定的`Identifier`終止正在下載或者上傳操作, 但如果是使用者手動關閉了應用, 系統就會取消所有後臺傳輸的會話, 官方建議, 如果要時候後臺操作的話, 把discretionary屬性設定成為YES, 可以獲得更好地效能.
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0);

NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration backgroundSessionConfigurationWithIdentifier:@"backgroundSessionConfiguration"]];
複製程式碼

使用NSURLSession建立Task

剛剛我們也說了, NSURLSession是有三個子類的Task, 所以這裡我們也要分開來說說.

NSURLSessionDataTask:

// 通過指定的NSURL來建立一個NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [urlSession dataTaskWithURL:[NSURL URLWithString:@""]];

// 通過指定的NSURL物件來建立, 並同時執行完對應的任務後通過completionHandler:返回NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [urlSession dataTaskWithURL:[NSURL URLWithString:@""]
                                           completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                           }];

// 通過指定的NSURLRequest物件來建立一個NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [urlSession dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];

// 通過指定的NSURLRequest物件來建立, 並同時執行完對應的任務後通過completionHandler:返回NSURLSessionDataTask
NSURLSessionDataTask *dataTask = [urlSession dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                               completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                                   }];
複製程式碼

-- NSURLSessionUploadTask:

// 通過指定的NSURLRequest物件來建立一個NSURLSessionUploadTask
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithStreamedRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];

// 通過指定的NSURLRequest物件來建立一個NSURLSessionUploadTask, 並且指定上傳時所需的資料來源
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                                              fromData:[NSData data]];

// 通過指定的NSURLRequest物件來建立一個NSURLSessionUploadTask, 並且指定上傳時所需的檔案源
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                                              fromFile:[NSURL URLWithString:@""]];

// 通過指定的NSURLRequest物件來建立, 指定上傳時所需的檔案源, 並且同時執行完對應的任務後通過completionHandler:來返回NSURLSessionUploadTask
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                                              fromFile:[NSURL URLWithString:@""]
                                                     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                                     }];

// 通過指定的NSURLRequest物件來建立, 指定上傳時所需的資料來源, 並且同時執行完對應的任務後通過completionHandler:來返回NSURLSessionUploadTask
NSURLSessionUploadTask *uploadTask = [urlSession uploadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                                              fromData:[NSData data]
                                                     completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                                     }];
複製程式碼

-- NSURLSessionDownloadTask:

// 通過指定的NSURL物件來建立一個NSURLSessionDownloadTask
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithURL:[NSURL URLWithString:@""]];

// 通過指定的NSURL物件來建立一個NSURLSessionDownloadTask, 並同時執行完對應的任務後通過completionHandler:返回NSURLSessionDownloadTask
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithURL:[NSURL URLWithString:@""]
                                                       completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {    
                                                       }];

// 通過指定的NSURLRequest物件來建立一個NSURLSessionDownloadTask
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]];

// 通過指定的NSURLRequest物件來建立一個NSURLSessionDownloadTask, 並同時執行完對應的任務後通過completionHandler:返回NSURLSessionDownloadTask
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@""]]
                                                           completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {                                                             
                                                           }];

// 通過指定的NSData物件來建立一個NSURLSessionDownloadTask, 這個NSData物件是之前下載失敗或者是停止下載了的資料, 這就是我們常說的斷點續傳
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithResumeData:[NSData data]];

// 通過指定的NSData物件來建立一個NSURLSessionDownloadTask, , 並同時執行完對應的任務後通過completionHandler:返回NSURLSessionDownloadTask, 同時也是支援斷點續傳
NSURLSessionDownloadTask *downloadTask = [urlSession downloadTaskWithResumeData:[NSData data]
                                                              completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
                                                              }];
複製程式碼

NSURLSessionStreamTask:

// 通過一個指定的NSNetService物件來建立NSURLSessionStreamTask
NSURLSessionStreamTask *streamTask = [urlSession streamTaskWithNetService:[[NSNetService alloc] init]];

// 通過一個指定的IP地址, 埠號來建立一個NSURLSessionStreamTask
NSURLSessionStreamTask *streamTask = [urlSession streamTaskWithHostName:@"192.168.1.1"
                                                                   port:8888];
複製程式碼

NSURLSessionDelegate

剛剛講完了三種Task, 這裡補充一下, 就是說我們無論會用哪一種Task, 我們都可以指定對應的代理, 這裡有一張NSURLSession代理關係圖:

3

代理類 作用
NSURLSessionDelegate 作為其他代理的最基類, 定義了最基礎的網路請求代理方法
NSURLSessionTaskDelegate 定義了網路請求任務的代理方法
NSURLSessionDownloadDelegate 定義了下載任務的代理方法, 比如獲取下載進度
NSURLSessionDataDelegate 定義了上傳任務或普通資料任務的代理方法
NSURLSessionStreamDelegate 這個代理方法是繼承於NSURLSessionTaskDelegate, 提供一個TCP/IP的連結代理方法.

詳細大家都會用代理方法, 這裡就不介紹了.


執行任務

剛剛說完了那麼多東西, 最後就差執行任務了:

[task resume];
複製程式碼

醬紫就完事啦, 如果還想了解更多的話, 可以去看看蘋果爸爸的官方文件.


工程地址

專案地址: https://github.com/CainRun/iOS-10-Characteristic/tree/master/10.Siri%20Intents%20UI


最後

碼字很費腦, 看官賞點飯錢可好

微信

支付寶

相關文章