原生網(wǎng)絡(luò)請求NSURLSession
- 同一個 session 發(fā)送多個請求,只需要建立一次連接(復(fù)用了TCP)
- 提供了全局的 session 并且可以統(tǒng)一配置献丑,使用更加方便
- 下載的時候是多線程異步處理涛贯,效率更高
NSURLSessionTask
- NSURLSessionTask 是一個抽象類诽嘉,如果要使用那么只能使用它的子類
- 一般使用它的兩個子類
- NSURLSessionDataTask 一般的網(wǎng)絡(luò)請求(如GET、POST)弟翘,上傳請求用它的子類NSURLSessionUploadTask虫腋。
- NSURLSessionDownloadTask主要用于處理下載請求,有很大的優(yōu)勢
使用示例
- GET請求
//確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=520&pwd=520&type=JSON"];
//創(chuàng)建 NSURLSession 對象
NSURLSession *session = [NSURLSession sharedSession];
/**
根據(jù)對象創(chuàng)建 Task 請求
url 方法內(nèi)部會自動將 URL 包裝成一個請求對象(默認是 GET 請求)
completionHandler 完成之后的回調(diào)(成功或失斝普汀)
param data 返回的數(shù)據(jù)(響應(yīng)體)
param response 響應(yīng)頭
param error 錯誤信息
*/
NSURLSessionDataTask *dataTask = [session dataTaskWithURL:url completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析服務(wù)器返回的數(shù)據(jù)
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
//默認在子線程中解析數(shù)據(jù)
NSLog(@"%@", [NSThread currentThread]);
}];
//發(fā)送請求(執(zhí)行Task)
[dataTask resume];
- POST請求
//確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
//創(chuàng)建可變請求對象
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url];
//修改請求方法
requestM.HTTPMethod = @"POST";
//設(shè)置請求體
requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//創(chuàng)建會話對象
NSURLSession *session = [NSURLSession sharedSession];
//創(chuàng)建請求 Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestM completionHandler:
^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析返回的數(shù)據(jù)
NSLog(@"%@", [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
}];
//發(fā)送請求
[dataTask resume];
代理方式
//確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login"];
//創(chuàng)建可變請求對象
NSMutableURLRequest *requestM = [NSMutableURLRequest requestWithURL:url];
//設(shè)置請求方法
requestM.HTTPMethod = @"POST";
//設(shè)置請求體
requestM.HTTPBody = [@"username=520&pwd=520&type=JSON" dataUsingEncoding:NSUTF8StringEncoding];
//創(chuàng)建會話對象岔乔,設(shè)置代理
/**
第一個參數(shù):配置信息
第二個參數(shù):設(shè)置代理
第三個參數(shù):隊列,如果該參數(shù)傳遞nil 那么默認在子線程中執(zhí)行
*/
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration]
delegate:self delegateQueue:nil];
//創(chuàng)建請求 Task
NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:requestM];
//發(fā)送請求
[dataTask resume];
常用的3個代理方法
-(void)URLSession:(NSURLSession *)session dataTask:(nonnull NSURLSessionDataTask *)dataTask
didReceiveResponse:(nonnull NSURLResponse *)response
completionHandler:(nonnull void (^)(NSURLSessionResponseDisposition))completionHandler {
//子線程中執(zhí)行
NSLog(@"接收到服務(wù)器響應(yīng)的時候調(diào)用 -- %@", [NSThread currentThread]);
self.dataM = [NSMutableData data];
//默認情況下不接收數(shù)據(jù)
//必須告訴系統(tǒng)是否接收服務(wù)器返回的數(shù)據(jù)
completionHandler(NSURLSessionResponseAllow);
}
-(void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveData:(NSData *)data {
NSLog(@"接受到服務(wù)器返回數(shù)據(jù)的時候調(diào)用,可能被調(diào)用多次");
//拼接服務(wù)器返回的數(shù)據(jù)
[self.dataM appendData:data];
}
-(void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didCompleteWithError:(NSError *)error {
NSLog(@"請求完成或者是失敗的時候調(diào)用");
//解析服務(wù)器返回數(shù)據(jù)
NSLog(@"%@", [[NSString alloc] initWithData:self.dataM encoding:NSUTF8StringEncoding]);
}
設(shè)置代理之后的強引用問題
NSURLSession 對象在使用的時候滚躯,如果設(shè)置了代理雏门,那么 session 會對代理對象保持一個強引用,在合適的時候應(yīng)該主動進行釋放
可以在控制器調(diào)用 viewDidDisappear 方法的時候來進行處理掸掏,可以通過調(diào)用 invalidateAndCancel 方法或者是 finishTasksAndInvalidate 方法來釋放對代理對象的強引用
- invalidateAndCancel 方法直接取消請求然后釋放代理對象
- finishTasksAndInvalidate 方法等請求完成之后釋放代理對象茁影。
[self.session finishTasksAndInvalidate];
- NSURLSessionDownloadTask下載請求
//確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_02.png"];
//創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//創(chuàng)建會話對象
NSURLSession *session = [NSURLSession sharedSession];
//創(chuàng)建會話請求
//優(yōu)點:該方法內(nèi)部已經(jīng)完成了邊接收數(shù)據(jù)邊寫沙盒的操作,解決了內(nèi)存飆升的問題
NSURLSessionDownloadTask *downTask = [session downloadTaskWithRequest:request
completionHandler:^(NSURL * _Nullable location, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//默認存儲到臨時文件夾 tmp 中丧凤,需要剪切文件到 cache
NSLog(@"%@", location);//目標(biāo)位置
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]
stringByAppendingPathComponent:response.suggestedFilename];
/**
fileURLWithPath:有協(xié)議頭
URLWithString:無協(xié)議頭
*/
[[NSFileManager defaultManager] moveItemAtURL:location toURL:[NSURL fileURLWithPath:fullPath] error:nil];
}];
//發(fā)送請求
[downTask resume];
- NSURLSessionDataTask下載請求
[[[NSURLSession sharedSession] dataTaskWithURL:[NSURL URLWithString:
@"http://120.25.226.186:32812/resources/images/minion_01.png"]
completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
//解析數(shù)據(jù)
UIImage *image = [UIImage imageWithData:data];
//回到主線程設(shè)置圖片
dispatch_async(dispatch_get_main_queue(), ^{
self.imageView.image = image;
});
}] resume];
如要獲取下載進度募闲,可以使用代理的方式進行下載
dataTask 和 downloadTask 下載對比
- NSURLSessionDataTask下載文件可以實現(xiàn)離線斷點下載,但是代碼相對復(fù)雜
- NSURLSessionDownloadTask
下載文件可以實現(xiàn)斷點下載愿待,但不能離線斷點下載
內(nèi)部已經(jīng)完成了邊接收數(shù)據(jù)邊寫入沙盒的操作
解決了下載大文件時的內(nèi)存飆升問題