iOS NSURLConnection和異步網絡請求

在平常應用中,咱們每每使用AFNetworking等第三方庫來實現網絡請求部分。這篇文章會簡要地介紹一下如何使用NSURLConnection來進行異步的網絡請求。網絡

咱們先看一個小demo異步

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    NSString *urlStr = @"http://www.baidu.com";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];
    
    //從這個試驗能夠看出,connection的函數在 mainrunloop運行for循環時根本沒法被調用,因而可知,這裏的connection是在mainThread中運行的。
    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self];
    
    for(int i = 0 ;i<10000;i++)
    {
        NSLog(@"%d",i);
    }
    
    NSLog(@"for end==========");
}



- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
    NSLog(@"good!!!!!!!!");
}

看下輸入ide

2014-05-05 10:34:18.861 UrlConnectionASyncTest[9988:60b] 9997
2014-05-05 10:34:18.862 UrlConnectionASyncTest[9988:60b] 9998
2014-05-05 10:34:18.862 UrlConnectionASyncTest[9988:60b] 9999
2014-05-05 10:34:18.862 UrlConnectionASyncTest[9988:60b] for end==========
2014-05-05 10:34:18.865 UrlConnectionASyncTest[9988:60b] good!!!!!!!!

查看蘋果的文檔會發現以下的解釋函數

By default, a connection is scheduled on the current thread in the default mode when it is created. If you create a connection with the initWithRequest:delegate:startImmediately: method and provide NO for the startImmediately parameter, you can instead schedule the connection on an operation queue before starting it with the start method.

You cannot reschedule a connection after it has started.

這就是說,若是你僅僅經過在主線程中使用initWithRequest:delegate:方法建立一個connection對象,它會默認地加入到mainThread中,這樣當數據返回時,會在main thread中執行,這就會影響UI的刷新。這種connection就是否是同步connection,不一樣於同步網絡請求函數sendSynchronousRequest,可是它的回調函數會在main thread中執行,會影響main thread中的其餘函數執行。oop

下面是官方文檔對NSURLConnection請求數據的3中方法的總結:url

To retrieve the contents of a URL synchronously: In code that runs exclusively on a background thread, you can call sendSynchronousRequest:returningResponse:error: to perform an HTTP request. This call returns when the request completes or an error occurs. For more details, see Retrieving Data Synchronously.

To retrieve the contents of a URL using a completion handler block: If you do not need to monitor the status of a request, but merely need to perform some operation when the data has been fully received, you can call sendAsynchronousRequest:queue:completionHandler:, passing a block to handle the results. For more details, see Retrieving Data Using a Completion Handler Block.

To retrieve the contents of a URL using a delegate object: Create a delegate class that implements at least the following delegate methods: connection:didReceiveResponse:, connection:didReceiveData:, connection:didFailWithError:, and connectionDidFinishLoading:. The supported delegate methods are defined in the NSURLConnectionDelegate, NSURLConnectionDownloadDelegate, and NSURLConnectionDataDelegate protocols.

那麼如何建立一個在其餘thread中執行回調函數的connection呢?系統提供了2套方法,spa

第一套是使用類方法,sendAsynchronousRequest:queue:completionHandler:線程

第二套是使用幾個對象方法,順序以下code

1.使用initWithRequest:delegate:startImmediately:生成一個不當即開始的connnection

2.經過scheduleInRunLoop:forMode: 或者 setDelegateQueue: 設置回調方法運行的thread,推薦使用第二個。

3.調用start開始connection請求。

下面給出一個demoorm

- (void)viewDidLoad
{
    [super viewDidLoad];
    // Do any additional setup after loading the view, typically from a nib.
    
    NSString *urlStr = @"http://www.baidu.com";
    NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:urlStr]];

    //從這個試驗能夠看出,connection的函數在 mainrunloop運行for循環時根本沒法被調用,因而可知,這裏的connection是在mainThread中運行的。
    // NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self];

    NSURLConnection *con = [[NSURLConnection alloc] initWithRequest:request delegate:self startImmediately:NO];

    [con setDelegateQueue:[[NSOperationQueue alloc] init]];
    [con start];
    
    for(int i = 0 ;i<10000;i++)
    {
        NSLog(@"%d",i);
    }
    
    NSLog(@"for end==========");
}



- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
  //  NSLog(@"data is %@",[[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]);
    NSLog(@"good!!!!!!!!");
}

結果以下

2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 344
2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 345
2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 346
2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 347
2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 348
2014-05-05 11:23:15.129 UrlConnectionASyncTest[10147:60b] 349
2014-05-05 11:23:15.130 UrlConnectionASyncTest[10147:60b] 350
2014-05-05 11:23:15.134 UrlConnectionASyncTest[10147:4207] good!!!!!!!!
2014-05-05 11:23:15.143 UrlConnectionASyncTest[10147:60b] 351
2014-05-05 11:23:15.144 UrlConnectionASyncTest[10147:60b] 352
2014-05-05 11:23:15.144 UrlConnectionASyncTest[10147:4207] good!!!!!!!!
2014-05-05 11:23:15.144 UrlConnectionASyncTest[10147:60b] 353
2014-05-05 11:23:15.144 UrlConnectionASyncTest[10147:60b] 354
2014-05-05 11:23:15.144 UrlConnectionASyncTest[10147:60b] 355
2014-05-05 11:23:15.145 UrlConnectionASyncTest[10147:60b] 356

能夠看出connection的回調函數已經再也不main thread中執行了!

相關文章
相關標籤/搜索