ios開發網路學習六:設定隊列請求與RunLoop

來源:互聯網
上載者:User

標籤:

#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

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.