国产探花免费观看_亚洲丰满少妇自慰呻吟_97日韩有码在线_资源在线日韩欧美_一区二区精品毛片,辰东完美世界有声小说,欢乐颂第一季,yy玄幻小说排行榜完本

首頁 > 系統 > iOS > 正文

ios NSURLSession使用說明及后臺工作流程分析

2019-11-07 23:14:05
字體:
來源:轉載
供稿:網友

ios NSURLsession使用說明及后臺工作流程分析 

2014-07-23 17:18 15708人閱讀 評論(1) 收藏 舉報 分類:

NSURLSession是iOS7中新的網絡接口,它與咱們熟悉的NSURLConnection是并列的。在程序在前臺時,NSURLSession與NSURLConnection可以互為替代工作。注意,如果用戶強制將程序關閉,NSURLSession會斷掉。

 NSURLSession提供的功能:1.通過URL將數據下載到內存2.通過URL將數據下載到文件系統3.將數據上傳到指定URL4.在后臺完成上述功能 工作流程如果我們需要利用NSURLSession進行數據傳輸我們需要:1.創建一個NSURLSessionConfiguration,用于第二步創建NSSession時設置工作模式和網絡設置:工作模式分為:一般模式(default):工作模式類似于原來的NSURLConnection,可以使用緩存的Cache,Cookie,鑒權。及時模式(ephemeral):不使用緩存的Cache,Cookie,鑒權。后臺模式(background):在后臺完成上傳下載,創建Configuration對象的時候需要給一個NSString的ID用于追蹤完成工作的Session是哪一個(后面會講到)。 網絡設置:參考NSURLConnection中的設置項。1. 創建一個NSURLSession,系統提供了兩個創建方法:sessionWithConfiguration:sessionWithConfiguration:delegate:delegateQueue:    第一個粒度較低就是根據剛才創建的Configuration創建一個Session,系統默認創建一個新的OperationQueue處理Session的消息。 第二個粒度比較高,可以設定回調的delegate(注意這個回調delegate會被強引用),并且可以設定delegate在哪個OperationQueue回調,如果我們將其設置為[NSOperationQueue mainQueue]就能在主線程進行回調非常的方便。 2.創建一個NSURLRequest調用剛才的NSURLSession對象提供的Task函數,創建一個NSURLSessionTask。 根據職能不同Task有三種子類:NSURLSessionUploadTask:上傳用的Task,傳完以后不會再下載返回結果;NSURLSessionDownloadTask:下載用的Task;NSURLSessionDataTask:可以上傳內容,上傳完成后再進行下載。 得到的Task,調用resume開始工作。 3.如果是細粒度的Session調用,Session與Delegate會在指定的OperationQueue中進行交互,以咱們下載例子,交互過程的順序圖如下(假如不需要鑒權,即非HTTPS請求):4.當不再需要連接調用Session的invalidateAndCancel直接關閉,或者調用finishTasksAndInvalidate等待當前Task結束后關閉。這時Delegate會收到URLSession:didBecomeInvalidWithError:這個事件。Delegate收到這個事件之后會被解引用。 5.如果是一個BackgroundSession,在Task執行的時候,用戶切到后臺,Session會和applicationDelegate做交互。當程序切到后臺后,在BackgroundSession中的Task還會繼續下載,這部分文檔敘述比較少,現在分三個場景分析下Session和Application的關系: 1)當加入了多個Task,程序沒有切換到后臺。這種情況Task會按照NSURLSessionConfiguration的設置正常下載,不會和ApplicationDelegate有交互。 2)當加入了多個Task,程序切到后臺,所有Task都完成下載。 在切到后臺之后,Session的Delegate不會再收到,Task相關的消息,直到所有Task全都完成后,系統會調用ApplicationDelegate的application:handleEventsForBackgroundURLSession:completionHandler:回調,之后“匯報”下載工作,對于每一個后臺下載的Task調用Session的Delegate中的URLSession:downloadTask:didFinishDownloadingToURL:(成功的話)和URLSession:task:didCompleteWithError:(成功或者失敗都會調用)。 之后調用Session的Delegate回調URLSessionDidFinishEventsForBackgroundURLSession:。 注意:在ApplicationDelegate被喚醒后,會有個參數ComplietionHandler,這個參數是個Block,這個參數要在后面Session的Delegate中didFinish的時候調用一下,如下:
@implementation APLAppDelegate     - (void)application:(UIApplication *)application handleEventsForBackgroundURLSession:(NSString *)identifier    completionHandler:(void (^)())completionHandler  {      BLog();      /*       Store the completion handler. The completion handler is invoked by the view controller's checkForAllDownloadsHavingCompleted method (if all the download tasks have been completed).       */        self.backgroundSessionCompletionHandler = completionHandler;  }  //……  @end     //Session的Delegate  @implementation APLViewController     - (void)URLSessionDidFinishEventsForBackgroundURLSession:(NSURLSession *)session  {      APLAppDelegate *appDelegate = (APLAppDelegate *)[[UIApplication sharedApplication] delegate];      if (appDelegate.backgroundSessionCompletionHandler) {          void (^completionHandler)() = appDelegate.backgroundSessionCompletionHandler;          appDelegate.backgroundSessionCompletionHandler = nil;          completionHandler();      }         NSLog(@"All tasks are finished");  }  @end  3)當加入了多個Task,程序切到后臺,下載完成了幾個Task,然后用戶又切換到前臺。(程序沒有退出)  切到后臺之后,Session的Delegate仍然收不到消息。在下載完成幾個Task之后再切換到前臺,系統會先匯報已經下載完成的Task的情況,然后繼續下載沒有下載完成的Task,后面的過程同第一種情況。 4)當加入了多個Task,程序切到后臺,幾個Task已經完成,但還有Task還沒有下載完的時候關掉強制退出程序,然后再進入程序的時候。(程序退出了) 最后這個情況比較有意思,由于程序已經退出了,后面沒有下完Session就不在了后面的Task肯定是失敗了。但是已經下載成功的那些Task,新啟動的程序也沒有聽“匯報”的機會了。經過實驗發現,這個時候之前在NSURLSessionConfiguration設置的NSString類型的ID起作用了,當ID相同的時候,一旦生成Session對象并設置Delegate,馬上可以收到上一次關閉程序之前沒有匯報工作的Task的結束情況(成功或者失敗)。但是當ID不相同,這些情況就收不到了,因此為了不讓自己的消息被別的應用程序收到,或者收到別的應用程序的消息,起見ID還是和程序的Bundle名稱綁定上比較好,至少保證唯一性。 總結就像前面說的,在普通的應用場景下NSURLSession與NSURLConnection相比沒有什么優勢,但是在程序切換到后臺之后Background的Session就顯得更加靈活了。 另外,現在主流的網絡開發框架AFNetworking已經更新到了2.0(只支持iOS 6 / iOS 7),其中最重要的一個更新就是添加了NSURLSession相關的支持。雖然就我現在(2013.10.13)看到他們的源碼中,還沒有完全的支持后臺的Session(或者說沒有考慮全我上述的后臺情況),但是大家有興趣可以關注一下他們后續的更新情況。[objc] view plain copy//////////////////////  代碼演示 01.URLSession 上傳,注意代理是 NSURLSessionTaskDelegate[objc] view plain copy//  //  MJViewController.m  //  01.URLSession 上傳  //  //  Created by apple on 14-4-30.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "MJViewController.h"    @interface MJViewController () <NSURLSessionTaskDelegate>    @end    @implementation MJViewController    - (void)viewDidLoad  {      [super viewDidLoad];        [self uploadFile1];  }    #PRagma mark - 監控上傳進度  - (void)uploadFile1  {      // 1. URL      NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"head8.png" withExtension:nil];      NSURL *url = [NSURL URLWithString:@"http://localhost/uploads/1.png"];            // 2. Request      NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:2.0f];      // 1> PUT方法      // PUT      //    1) 文件大小無限制      //    2) 可以覆蓋文件      // POST      //    1) 通常有限制2M      //    2) 新建文件,不能重名      request.HTTPMethod = @"PUT";            // 2> 安全認證      // admin:123456      // result base64編碼      // Basic result      /**      BASE 64是網絡傳輸中最常用的編碼格式 - 用來將二進制的數據編碼成字符串的編碼方式            BASE 64的用法:      1> 能夠編碼,能夠解碼      2> 被很多的加密算法作為基礎算法      */      NSString *authStr = @"admin:123456";      NSData *authData = [authStr dataUsingEncoding:NSUTF8StringEncoding];      NSString *base64Str = [authData base64EncodedStringWithOptions:0];      NSString *resultStr = [NSString stringWithFormat:@"Basic %@", base64Str];      [request setValue:resultStr forHTTPHeaderField:@"Authorization"];            // 3. Session,全局單例(我們能夠給全局的session設置代理嗎?如果不能為什么?)      // sharedSession是全局共享的,因此如果要設置代理,需要單獨實例化一個Session      /**      NSURLSessionConfiguration(會話配置)            defaultSessionConfiguration;       // 磁盤緩存,適用于大的文件上傳下載      ephemeralSessionConfiguration;     // 內存緩存,以用于小的文件交互,GET一個頭像      backgroundSessionConfiguration:(NSString *)identifier; // 后臺上傳和下載      */      NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];            NSURLSession *session = [NSURLSession sessionWithConfiguration:config delegate:self delegateQueue:[[NSOperationQueue alloc]init]];            // 需要監聽任務的執行狀態      NSURLSessionUploadTask *task = [session uploadTaskWithRequest:request fromFile:fileURL];            // 4. resume      [task resume];  }    #pragma mark - 上傳進度的代理方法  - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didSendBodyData:(int64_t)bytesSent totalBytesSent:(int64_t)totalBytesSent totalBytesExpectedToSend:(int64_t)totalBytesExpectedToSend  {      // bytesSent totalBytesSent totalBytesExpectedToSend      // 發送字節(本次發送的字節數)    總發送字節數(已經上傳的字節數)     總希望要發送的字節(文件大小)      NSLog(@"%lld-%lld-%lld-", bytesSent, totalBytesSent, totalBytesExpectedToSend);      // 已經上傳的百分比      float progress = (float)totalBytesSent / totalBytesExpectedToSend;      NSLog(@"%f", progress);  }    #pragma mark - 上傳完成的代理方法  - (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error  {      NSLog(@"完成 %@", [NSThread currentThread]);  }  @end  02.Session下載

[objc] view plain copy//  //  MJViewController.m  //  02.Session下載  //  //  Created by apple on 14-4-30.  //  Copyright (c) 2014年 itcast. All rights reserved.  //    #import "MJViewController.h"    @interface MJViewController () <NSURLSessionDownloadDelegate>  @property (weak, nonatomic) IBOutlet UIImageView *imageView;  @end    /**  // 下載進度跟進  - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask  didWriteData:(int64_t)bytesWritten  totalBytesWritten:(int64_t)totalBytesWritten  totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite;    didWriteData totalBytesWritten totalBytesExpectedToWrite  本次寫入的字節數 已經寫入的字節數   預期下載的文件大小    // 完成下載  - (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask  didFinishDownloadingToURL:(NSURL *)location;  */    @implementation MJViewController    - (void)viewDidLoad  {      [super viewDidLoad];            [self downloadTask];  }    #pragma mark - 下載(GET)  - (void)downloadTask  {      // 1. URL      NSURL *url = [NSURL URLWithString:@"http://localhost/itcast/images/head1.png"];            // 2. Request      NSURLRequest *request = [NSURLRequest requestWithURL:url cachePolicy:0 timeoutInterval:2.0];            // 3. Session      NSURLSession *session = [NSURLSession sharedSession];            // 4. download      [[session downloadTaskWithRequest:request completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {          // 下載的位置,沙盒中tmp目錄中的臨時文件,會被及時刪除          NSLog(@"下載完成 %@ %@", location, [NSThread currentThread]);          /**          document       備份,下載的文件不能放在此文件夾中          cache          緩存的,不備份,重新啟動不會被清空,如果緩存內容過多,可以考慮新建一條線程檢查緩存目錄中的文件大小,自動清理緩存,給用戶節省控件          tmp            臨時,不備份,不緩存,重新啟動iphone,會自動清空          */          // 直接通過文件名就可以加載圖像,圖像會常駐內存,具體的銷毀有系統負責          // [UIImage imageNamed:@""];          dispatch_async(dispatch_get_main_queue(), ^{              // 從網絡下載下來的是二進制數據              NSData *data = [NSData dataWithContentsOfURL:location];              // 這種方式的圖像會自動釋放,不占據內存,也不需要放在臨時文件夾中緩存              // 如果用戶需要,可以提供一個功能,保存到用戶的相冊即可              UIImage *image = [UIImage imageWithData:data];                            self.imageView.image = image;          });      }] resume];        //    [task resume];  }    @end  http://www.cocoachina.com/applenews/devnews/2013/1106/7304.html
發表評論 共有條評論
用戶名: 密碼:
驗證碼: 匿名發表
主站蜘蛛池模板: 奉节县| 城步| 萨迦县| 嘉善县| 积石山| 益阳市| 米脂县| 团风县| 瑞金市| 临夏市| 常熟市| 冷水江市| 衡水市| 仙游县| 琼海市| 桃江县| 阿城市| 柳林县| 民勤县| 兴业县| 叙永县| 上饶市| 安阳县| 灵寿县| 湘潭县| 贵南县| 新源县| 陆川县| 淳化县| 杂多县| 韩城市| 屯昌县| 黄冈市| 永修县| 金溪县| 罗源县| 湖口县| 江陵县| 怀来县| 资源县| 阿图什市|