在平常应用中,咱们每每使用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中执行了!