首页 > 代码库 > iOS网络: NSURLConnection进行异步请求

iOS网络: NSURLConnection进行异步请求

介绍:
   iOS 的应用,一般是需要通过网络进行数据的交互的,这样你的应用就成为了联机的应用了。 

   iOS SDK 允许我们向网络发送请求,并且能够很方便的通过 NSURLConnection 这个类 来获取和发送数据,我们可以通过 NSJSONSerialization 对 JSON 进行序列化和反序列化。 XML 的解析则使用 NSXMLParser 类。可以通过 Twitter 框架进行 Twitter 进行连接。 

 

一  通过NSURLConnection进行异步下载

1.
NSURLConnection 提供了两种方式来实现连接,一种是同步的另一种是异步的,异步 的连接将会创建一个新的线程,这个线程将会来负责下载的动作。而对于同步连接,在下载 连接和处理通讯时,则会阻塞当前调用线程。 
 
许多开发者都会认为同步的连接将会堵塞主线程,其实这种观点是错误的。一个同步的连接是会阻塞调用它的线程。如果你在主线程中创建一个同步连接,没错,主线程会阻塞。 但是如果你并不是从主线程开启的一个同步的连接,它将会类似异步的连接一样。因此这种情况并不会堵塞你的主线程。事实上,同步和异步的主要区别就是运行 runtime 为会异步连接创建一个线程,而同步连接则不会。 
 
2.
为了能够创建一个异步的请求连接,我们需要做如下的操作。
1. 创建一个 NSSring 类型的 URL 连接字符串。
2. 把 NSString 类型转化成 NSURL 类型。
3. 把我们的URL对象赋值到 NSURLRequest 对象中,如果是多个连接请求,请使用 NSMutableURLRequest.
4. 创建一个 NSURLConnection 的连接实例,然后把我们定义好的 URL 请求赋值过去。 
  我们可以通过 NSURLConnection 的 sendAsynchronousRequest:queue:completionHandler 这个方法创建一个异步的 URL 连接对象。这个方法的参数如下: 
sendAsynchronousRequest
   异步请求
Queue  
  一个操作队列,我们可以很轻松的分配和初始化一个操作队列,然后可以根据我们需求添加到这个参数中。

completionHandler

  这是一个 block 对象,当我们异步的连接操作完成之后,无论我们的异步操作是否成功,都会执行这个 block,这个 block 对象都能够接收到如下三个参数:

    1).一个 NSURLResopne,这个对象封装了服务器返回给我们 response。

    2).NSData,可选的,这个是我们通过 URL 请求返回的数据。

    3).NSError 类型的对象,如果请求中有错误发生。 

 注意:

sendAsynchronousRequest:queue:completionHandler: 方法不会在主线程中调用。因此如果你想执行一个跟 UI 相关的任务,那么请回到主线程中。 

 

例子:

- (void)sendAsynNetWork{    NSString *urlString = @"http://www.apple.com";    NSURL *url = [NSURL URLWithString:urlString];    NSURLRequest *urlRequest = [NSURLRequest requestWithURL:url];    NSOperationQueue *queue = [[NSOperationQueue alloc]init];    //发送异步请求    [NSURLConnection sendAsynchronousRequest:urlRequest queue:queue completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {        if ([data length] > 0 && connectionError == nil) {            NSString *html = [[NSString alloc]initWithData:data encoding:NSUTF8StringEncoding];            NSLog(@"HTML = %@",html);            //保存从网络上下载的数据到你的硬盘中            //1.获取存储路径            NSString *documentsDir = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES)objectAtIndex:0];            //将文件名添加到存储路径上,形成文件路径            NSString *filePath = [documentsDir stringByAppendingPathComponent:@"apple.html"];            //将数据写入文件 存到硬盘            [data writeToFile:filePath atomically:YES];            NSLog(@"Successfully saved the file to %@",filePath);        }        else if ([data length] == 0 && connectionError == nil){            NSLog(@"Nothing was downloaded");        }        else if (connectionError != nil){            NSLog(@"connectionError happened = %@",connectionError);        }    }];}
在 iOS SDK 早期的版本中,URL 连接使用的是 delegation 模型,不过,现在全部都使用 block 了,你不用在考虑实现 delegate 方法。 

 

二. 处理异步连接中的超时

创建一个异步的请求的时候,你想设置一个响应超时的值,来完善你的应用程序 

讨论:

当初始化 NSURLRequest 这个对象,并且把这个对象传递给 URL 连接对象的时候,你可以使用 requestWithURL:cachePolicy:timeoutInterval:这个类方法,将超时的值传递给 timeoutInterval 参数。 

这里详细看第二个参数 cachePolicy:  参数值在 NSURLRequestCachePolicy(缓存策略) 枚举中选择:

typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)

{

 

1> NSURLRequestUseProtocolCachePolicy = 0, 默认的缓存策略, 如果缓存不存在,直接从服务端获取。如果缓存存在,会根据response中的Cache-Control字段判断下一步操作,如: Cache-Control字段为must-revalidata, 则询问服务端该数据是否有更新,无更新的话直接返回给用户缓存数据,若已更新,则请求服务端.
 
2> NSURLRequestReloadIgnoringLocalCacheData = http://www.mamicode.com/1, 忽略本地缓存数据,直接请求服务端.
 
3> NSURLRequestReloadIgnoringLocalAndRemoteCacheData = http://www.mamicode.com/4, 忽略本地缓存,代理服务器以及其他中介,直接请求源服务端.
 
4> NSURLRequestReloadIgnoringCacheData = http://www.mamicode.com/NSURLRequestReloadIgnoringLocalCacheData
 
5> NSURLRequestReturnCacheDataElseLoad = 2, 有缓存就使用,不管其有效性(即忽略Cache-Control字段), 无则请求服务端.
 
6> NSURLRequestReturnCacheDataDontLoad = 3, 死活加载本地缓存. 没有就失败. (确定当前无网络时使用)
 
7> NSURLRequestReloadRevalidatingCacheData = http://www.mamicode.com/5, 缓存数据必须得得到服务端确认有效才使用(貌似是NSURLRequestUseProtocolCachePolicy中的一种情况)
 
};
Tips: URL Loading System默认只支持如下5中协议: 其中只有http://和https://才有缓存策略.
(1) http://
(2) https://
(3) ftp://
(4) file://
(5) data://

 

 //设置更详细的request  第二个参数缓存策略 第三个参数最大等待时间    NSURLRequest *urlrequest1 = [NSURLRequest requestWithURL:url cachePolicy:NSURLRequestReloadIgnoringLocalAndRemoteCacheData timeoutInterval:15.0f];

 

 
 
 
 

iOS网络: NSURLConnection进行异步请求