NSURLSession的基礎用法
NSURLSession的基礎用法
- (void)viewDidLoad {
[super viewDidLoad];
NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration];
NSURLSession *urlSession = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:[[NSOperationQueue alloc] init]];
NSMutableURLRequest *req = [NSMutableURLRequest requestWithURL:[NSURL URLWithString:kRemotePAJsonURL]];
req.HTTPMethod = @"POST";
NSURLSessionDataTask *dataTask = [urlSession dataTaskWithRequest:req];
[dataTask resume];
NSLog(@"本次dataTask:%@", dataTask);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveResponse:(NSURLResponse *)response
completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
{
NSLog(@"收到響應:%@ \ndataTask:%@", response, dataTask);
self.mData = [NSMutableData data];
NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
completionHandler(disposition);
}
- (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask
didReceiveData:(NSData *)data
{
NSLog(@"%@收到data:%ld",[NSThread currentThread] ,data.length);
[self.mData appendData:data];
if (self.mData.length > 3000) {
[dataTask cancel];
}
}
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task
didCompleteWithError:(nullable NSError *)error
{
NSLog(@"完成, error:%@", error);
if (!error) {
//在完成的時候,之前收到的data怎麼取到?不借助其他的變數,在該方法裡取不到?
NSDictionary *dict = [NSJSONSerialization JSONObjectWithData:self.mData options:NSJSONReadingAllowFragments error:nil];
NSLog(@"%@", dict);
}
//不把本次session Invalidate,那麼session持有的delegate不會被釋放.
[session finishTasksAndInvalidate];
}
對於方法
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration
delegate:(nullable id <NSURLSessionDelegate>)delegate
delegateQueue:(nullable NSOperationQueue *)queue;
delegate和delegateQueue會被urlSession強引用.按蘋果的文件說明:delegate會在URLSession:didBecomeInvalidWithError
結束後釋放.但事實上,要想讓delegate在didBecomeInvalidWithError
結束後釋放,需要先把session Invalidate.否則,session持有的delegate不會被釋放.這句話的正確理解應該是,當一個session invalidate後,delegate要等到URLSession:didBecomeInvalidWithError
結束後才會被釋放.對於delegateQueue,實際使用時delegateQueue不能是主佇列的.當delegateQueue不是主佇列時,didReceiveData:方法將隨機在某個執行緒執行.
基本上一個APP,生成一個urlSession就夠了.沒必要一次請求,建立一個session,請求結束後又將session Invalidate.因此也就沒必要去管delegate和delegateQueue的記憶體釋放問題,這三個物件基本上是等到APP結束才會銷燬的.最佳做法之一就是使用GCD確保只生成一個session,然後使用該session來管理所有的請求.
對於代理方法: - (void)URLSession:(NSURLSession *)session dataTask:(NSURLSessionDataTask *)dataTask didReceiveResponse:(NSURLResponse *)response completionHandler:(void (^)(NSURLSessionResponseDisposition disposition))completionHandler
在該方法中,為什麼收到響應後,還要呼叫completionHandler block?
因為在該方法中,通過disposition引數,呼叫completionHandler後,可以更細粒度的控制本次請求是繼續還是取消還是轉為下載任務.如果是取消,則後面請求的響應體不會接收.如果是轉為下載任務,那麼通過呼叫completionHandler,NSURLSession將呼叫Delegate的 URLSession:dataTask:didBecomeDownloadTask:
方法並將新生成的Download task物件作為引數傳入。在此呼叫之後,Delegate將不再接收來自Data task的回撥訊息,並開始接收Download task的回撥訊息。
注意:如果不呼叫
NSURLSessionResponseDisposition disposition = NSURLSessionResponseAllow;
completionHandler(disposition);
後面的didReceiveData:代理方法將不會執行.
疑問
NSURLSession物件是被誰強引用了?如何釋放?
NSURLSession物件應該是被系統的runloop強引用了,就類似於定時器一樣,需要invalid後,才會被釋放銷燬.
題外話:如果timer屬性是strong,那麼invalidate後最好將其置為nil,否則invalid後timer因為還有人持有它,而不能銷燬.strong情況下,timer的釋放:[self.timer invalidate];self.timer = nil;
定時器物件是註冊到runloop裡的,應該通過invalidate來告訴runloop釋放它.所以self不應該持有該物件,因此timer屬性最好為weak.NSURLSession的生命週期?
在didCompleteWithError:完成的時候,之前收到的data怎麼取到?不借助其他的變數,在該方法裡取不到?
相關文章
- css的基礎用法(下)CSS
- SqlSugar基礎用法SqlSugar
- print基礎用法
- ES 基礎用法
- JSTL基礎用法JS
- Promise基礎用法Promise
- Promise 基礎用法Promise
- JavaScript:async/await的基礎用法JavaScriptAI
- 060、Vue3+TypeScript基礎,插槽的基礎用法VueTypeScript
- dos-基礎用法
- git 基礎用法梳理Git
- nodeJS基礎 Stream用法NodeJS
- 教程:Laravel 集合(Collection)的基礎用法Laravel
- Linux——基礎命令用法(上)Linux
- Linux——基礎命令用法(下)Linux
- Redux 入門 -- 基礎用法Redux
- go語言基礎之——iota的用法Go
- 【css基礎】如何理解transform的matrix()用法CSSORM
- Numpy基本用法(很基礎的點哦)
- node基礎(4)---Stream的用法詳解
- Redis基礎——剖析基礎資料結構及其用法Redis資料結構
- Elaticsearch(一)--基礎原理及用法
- SpringDataMongo連線MongoDB基礎用法SpringMongoDB
- C# 中的 Mutex(互斥體)基礎用法C#Mutex
- Laravel-excel3.1最基礎用法LaravelExcel
- Java基礎知識整理之this用法Java
- Python pip(管理模組工具)基礎用法Python
- Go基礎系列:雙層channel用法示例Go
- Java基礎 | Stream流原理與用法總結Java
- shell入門基礎&常見命令及用法
- 逍遙自在學C語言 | 位運算子的基礎用法C語言
- C# 基礎知識系列- 9 字串的更多用法(二)C#字串
- Python中基礎資料型別(List、Tuple、Dict)的概念和用法Python資料型別
- 資料採集元件:Flume基礎用法和Kafka整合元件Kafka
- nmap命令-----基礎用法(系統漏洞掃描之王-nmap)
- [今日白學]元件的基礎的基礎的基礎元件
- 資料倉儲元件:Hive環境搭建和基礎用法元件Hive
- Java基礎篇(04):日期與時間API用法詳解JavaAPI
- python基礎中的基礎Python