標籤:
#import "ViewController.h"@interface ViewController ()<NSURLConnectionDataDelegate>@end@implementation ViewController-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event{ [self newThreadDelegate2];}-(void)delegate1{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"]]; //設定代理 //代理方法:預設是在主線程中調用的 NSURLConnection *connect = [NSURLConnection connectionWithRequest:request delegate:self]; //設定代理方法在哪個線程中調用 //[NSOperationQueue alloc]init]] 開子線程 //[NSOperationQueue mainQueue] 不能這樣設定 [connect setDelegateQueue:[[NSOperationQueue alloc]init]]; //[connect setDelegateQueue:[NSOperationQueue mainQueue]]; NSLog(@"-------");}-(void)delegate2{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"]]; //設定代理 //代理方法:預設是在主線程中調用的 NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO]; [connect setDelegateQueue:[[NSOperationQueue alloc]init]]; //開始發送請求 [connect start]; NSLog(@"-------");}-(void)newThreadDelegate1{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"]]; //設定代理 //代理方法:預設是在主線程中調用的 //該方法內部其實會將connect對象作為一個source添加到當前的runloop中,指定運行模式為預設 NSURLConnection *connect = [NSURLConnection connectionWithRequest:request delegate:self]; //設定代理方法在哪個線程中調用 [connect setDelegateQueue:[[NSOperationQueue alloc]init]]; //[[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1000]]; [[NSRunLoop currentRunLoop]run]; NSLog(@"---%@----",[NSThread currentThread]); }); }-(void)newThreadDelegate2{ dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"]]; //設定代理 //代理方法:預設是在主線程中調用的 NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO]; [connect setDelegateQueue:[[NSOperationQueue alloc]init]]; //開始發送請求 //如如果connect對象沒有添加到runloop中,那麼該方法內部會自動的添加到runloop //注意:如果當前的runloop沒有開啟,那麼該方法內部會自動獲得當前線程對應的runloop對象並且開啟 [connect start]; NSLog(@"---%@----",[NSThread currentThread]); });}#pragma mark ----------------------#pragma mark NSURLConnectionDataDelegate-(void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response{ NSLog(@"didReceiveResponse---%@",[NSThread currentThread]);}@end
#####1 NSURLConnection和Runloop(面試)
(1)兩種為NSURLConnection設定代理方式的區別
```objc
//第一種設定方式:
//通過該方法設定代理,會自動的發送請求
// [[NSURLConnection alloc]initWithRequest:request delegate:self];
//第二種設定方式:
//設定代理,startImmediately為NO的時候,該方法不會自動發送請求
NSURLConnection *connect = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:NO];
//手動通過代碼的方式來發送請求
//注意該方法內部會自動的把connect添加到當前線程的RunLoop中在預設模式下執行
[connect start];
```
(2)如何控制代理方法在哪個線程調用
```objc
//說明:預設情況下,代理方法會在主線程中進行調用(為了方便開發人員拿到資料後處理一些重新整理UI的操作不需要考慮到線程間通訊)
//設定代理方法的執行隊列
[connect setDelegateQueue:[[NSOperationQueue alloc]init]];
```
(3)開子線程發送網路請求的注意點,適用於自動發送網路請求模式
```objc
//在子線程中發送網路請求-調用startf方法發送
-(void)createNewThreadSendConnect1
{
//1.建立一個非主隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.封裝操作,並把任務添加到隊列中執行
[queue addOperationWithBlock:^{
NSLog(@"%@",[NSThread currentThread]);
//2-1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=dd&pwd=ww&type=JSON"];
//2-2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//2-3.使用NSURLConnection設定代理,發送網路請求
NSURLConnection *connection = [[NSURLConnection alloc]initWithRequest:request delegate:self startImmediately:YES];
//2-4.設定代理方法在哪個隊列中執行,如果是非主隊列,那麼代理方法將再子線程中執行
[connection setDelegateQueue:[[NSOperationQueue alloc]init]];
//2-5.發送網路請求
//注意:start方法內部會把當前的connect對象作為一個source添加到當前線程對應的runloop中
//區別在於,如果調用start方法開發送網路請求,那麼再添加source的過程中,如果當前runloop不存在
//那麼該方法內部會自動建立一個當前線程對應的runloop,並啟動。
[connection start];
}];
}
//在子線程中發送網路請求-自動發送網路請求
-(void)createNewThreadSendConnect2
{
NSLog(@"-----");
//1.建立一個非主隊列
NSOperationQueue *queue = [[NSOperationQueue alloc]init];
//2.封裝操作,並把任務添加到隊列中執行
[queue addOperationWithBlock:^{
//2-1.確定請求路徑
NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/login?username=dd&pwd=ww&type=JSON"];
//2-2.建立請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
//2-3.使用NSURLConnection設定代理,發送網路請求
//注意:該方法內部雖然會把connection添加到runloop,但是如果當前的runloop不存在,那麼不會主動建立。
NSURLConnection *connection = [NSURLConnection connectionWithRequest:request delegate:self];
//2-4.設定代理方法在哪個隊列中執行,如果是非主隊列,那麼代理方法將再子線程中執行
[connection setDelegateQueue:[[NSOperationQueue alloc]init]];
//2-5 建立當前線程對應的runloop,並開啟
[[NSRunLoop currentRunLoop]run];
}];
}
```
總結:也就是說發送網路請求在設定回調的隊列的時候,回調的任務預設在主線程,若是設定回調隊列在子線程,則毀掉成功後不會調用代理方法,解決辦法:1:調用start方法: start方法內部會把當前的connect對象作為一個source添加到當前線程對應的runloop中,
如果調用start方法開發送網路請求,那麼再添加source的過程中,如果當前runloop不存在那麼該方法內部會自動建立一個當前線程對應的runloop,並啟動。每條線程都必須有自己的runloop來處理事件 2:若是不調用start方法,則需要自己建立runloop並調用run方法,
dispatch_async(dispatch_get_global_queue(0, 0), ^{ NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/login?username=123&pwd=123&type=JSON"]]; //設定代理 //代理方法:預設是在主線程中調用的 //該方法內部其實會將connect對象作為一個source添加到當前的runloop中,指定運行模式為預設 NSURLConnection *connect = [NSURLConnection connectionWithRequest:request delegate:self]; //設定代理方法在哪個線程中調用 [connect setDelegateQueue:[[NSOperationQueue alloc]init]]; //[[NSRunLoop currentRunLoop] runMode:UITrackingRunLoopMode beforeDate:[NSDate dateWithTimeIntervalSinceNow:1000]]; [[NSRunLoop currentRunLoop]run]; NSLog(@"---%@----",[NSThread currentThread]); }); }
二者的區別就在於:1:調用start如果調用start方法開發送網路請求,那麼再添加source的過程中,如果當前runloop不存在那麼該方法內部會自動建立一個當前線程對應的runloop,並啟動 2:而下面的方法雖自動發送請求,也會
將connect對象作為一個source添加到當前的runloop中,指定運行模式為預設,但是如果當前子線程的runloop不存在則不會自動建立需要手動建立
NSURLConnection *connect = [NSURLConnection connectionWithRequest:request delegate:self];
ios開發網路學習六:設定隊列請求與RunLoop