- NSURLConnection在 iOS9 被宣布棄用,逐漸被 NSURLSession 替代;
- NSURLSession 、 NSURLSessionConfiguration 、NSURLSessionTask 常用三個類;
- AFNetWorking 從2.0版本開始,就是在 NSURLSession 的基礎上封裝的;
NSURLSession
使用:
1 - 通過NSURLSession的實例創建 task 任務;
2 - resume 執行 task 任務
NSURLSessionTask
可以理解為任務: 數據請求任務,下載任務,上傳任務等;
- NSURLSessionTask 的子類
NSURLSessionDataTask 數據請求
NSURLSessionUploadTask 上傳
NSURLSessionDownloadTask 下載
NSURLSessionDataTask 數據請求任務
dataTask 是執行數據請求相關的任務,但也可以用來執行上傳和下載相關的任務,是我們使用最多的task;
- block 形式
簡單的get請求:
如果返回值比較簡單,則用這種簡單的block方式。
NSURLSession *session = [NSURLSession sharedSession]; //單例創建session對象
NSURL *url = [NSURL URLWithString: "http://www.baidu.com/signin?username=13800138008&password=123456"];
// 初始化task
NSURLSessionTask *task = [session dataTaskWithURL:url completionHandler:^(NSData *data, NSURLResponse *response, NSError error) {
//數據處理
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
[task resume]; // 啟動任務 :所有類型的task都要調用resume方法才會開始進行請求
簡單的post請求:
NSURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString: @"http://www.baidu.com/signin"];
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
request.HTTPMethod = @"POST"; //post請求
request.HTTPBody = [@"username=13800138008&password=123456" dataUsingEncoding:
NSUTF8StringEncoding];
// 通過request初始化task
NSURLSessionTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
[task resume];
get 和 post 的區別:
請求方式 | 初始化task | 參數方式 |
---|---|---|
get | url | 參數拼接在 urlString 后面 |
post | request | 將參數通過 utf8 編碼,然后放在request 的body中 |
- NSURLSessionDataDelegate 代理形式
簡單的數據可以用 block 的方式進行處理,如果返回的數據比較復雜,或者相對數據進一步處理,則使用 NSURLSession 的 delegate。
delegate 分幾個階段 : 響應,接收數據,請求完成;
以get為例:
//創建session: session的delegate屬性是只讀的;delegateQueue 表示代理方法在哪個隊列中執行;
[NSURLSessionConfiguration defaultSessionConfiguration] 表示默認配置
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
// 創建任務
NSURLSessionDataTask *task = [session dataTaskWithRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.baidu.com/login?userName=13800138008&password=123456"]]];
[task resume]; // 啟動任務
delegate方法:
// 接收到服務器的響應
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition))completionHandler {
completionHandler(NSURLSessionResponseAllow); // 允許處理服務器的響應,才會繼續接收服務器返回的數據
}
// 接收服務器的數據(會調用多次)
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
// 處理接收到的數據
}
// 請求完成
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(NSError *)error {
// 請求完成,處理成功的數據或者拿到錯誤的error值
}
NSURLSessionDownloadTask 下載任務
和 一樣,有通過 url 和 request 兩種方式來初始化 session;
- 通過 url 來初始化,bloc形式:
SURLSession *session = [NSURLSession sharedSession];
NSURL *url = [NSURL URLWithString:@"http://www.baidu.com/source/icon/my.png"] ;
NSURLSessionDownloadTask *task = [session downloadTaskWithURL:url completionHandler:^(NSURL *location, NSURLResponse *response, NSError *error) {
// 返回的 location 是沙盒中tmp文件夾下的一個臨時url,文件下載后會存到這個位置,由于tmp中的文件隨時可能被刪除,所以我們需要自己需要把下載的文件挪到需要的地方
NSString *path = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent: response.suggestedFilename];
// 移動文件; response.suggestedFilename 是 url 中的最后一部分,如:my.png
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:path]
error:nil];
}];
[task resume]; // 啟動任務
- NSURLSessionDownloadDelegate 代理的形式:
// 每次寫入調用(會調用多次)
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didWriteData:(int64_t)bytesWritten totalBytesWritten:(int64_t)totalBytesWritten totalBytesExpectedToWrite:(int64_t)totalBytesExpectedToWrite {
// 可在這里通過已寫入的長度和總長度算出下載進度
CGFloat progress = 1.0 * totalBytesWritten / totalBytesExpectedToWrite;
NSLog(@"%f",progress);
}
// 下載完成調用
- (void)URLSession:(NSURLSession *)session downloadTask:(NSURLSessionDownloadTask *)downloadTask didFinishDownloadingToURL:(NSURL *)location {
// location 還是一個臨時路徑,需要自己挪到需要的路徑(caches下面)
NSString *filePath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask,YES) lastObject] stringByAppendingPathComponent:downloadTask.response.suggestedFilename];
//移動文件
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:filePath] error:nil];
}
// 任務完成調用
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
}
- 斷點下載
這種斷點下載只支持應用內斷點,如果程序在下載過程中途關閉,則不能恢復下載。
// 取消下載 :用這種方式取消下載,可以得到將來用來恢復的數據,保存起來
[self.task cancelByProducingResumeData:^(NSData *resumeData) {
self.resumeData = resumeData; //保存數據
}];
// 下載失敗導致的下載中斷會進入此協議方法,也可以得到用來恢復的數據
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
// 保存恢復數據
self.resumeData = error.userInfo[NSURLSessionDownloadTaskResumeData];
}
// 恢復下載時接過保存的恢復數據
self.task = [self.session downloadTaskWithResumeData:self.resumeData];
[self.task resume]; // 啟動任務
NSURLSessionUploadTask 上傳任務
上傳方式有兩種:
1 -
NSURLSessionUploadTask *task = [[NSURLSession sharedSession] uploadTaskWithRequest:request fromFile:fileName completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
}];
2 - post 方法: body 參數需要填寫request的請求體(http協議規定格式的大長串)
出于安全考慮,用這種方法比較多;
[self.session uploadTaskWithRequest:request fromData: body completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
NSLog(@"%@", [NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:nil]);
}];
每個task 自身有都擁有下面幾個方法
- (void)suspend; 暫停當前任務
- (void)resume; 啟動任務,也可以喚醒suspend狀態的任務
- (void)cancel; 取消當前的任務,也可以向處于suspend狀態的任務發送cancel消息,任務如果被取消便不能再恢復到之前的狀態。
NSURLSessionConfiguration 配置
- 默認配置
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
config.timeoutIntervalForRequest = 10; // 超時時間
config.allowsCellularAccess = YES; // 是否允許使用蜂窩網絡(后臺傳輸不適用)
- task有三種配置
+ (NSURLSessionConfiguration *)defaultSessionConfiguration; 默認模式,會將緩存存儲在磁盤上
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration; 瞬時會話模式,不會創建持久性存儲的緩存
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier;后臺會話模式,允許程序在后臺進行上傳下載工作