转载自:http://blog.sina.com.cn/s/blog_8157560c0101kt7h.html
1. 也就是说在IOS 7.1 之后你想用网络请求的话有两种途径,NSUrlSession, 想要兼容旧版本的话,可以就NSUrlConnetion
2. 如果想要上传数据的话,可以用NSURLRequest 包装上传的内容,再利用NSURLSession\NSURLConncetion
NSURLSession 使用时要确定三个条件: type of Session, type of task, isForeground, session 创建时是根据一个config类来生成的。
1.)三种类型session. 默认的session类型,它会利用磁盘将url认证信息存储在用户钥匙串中,临时session类则不会存储,一旦程序出问题,它就会抛出清空当前url信息; 最后一种是后台session,类型默认类型。
2.)任务类型则有三种,数据型任务,它是临时性操作,进行request的发送与接收是利用以NSData类,也因此不支持bg(后台)session.下载任务,上传任务:这两种支持后台session操作,当程序在后台运行时,仍然可以进行数据的上传与下载。
当程序进入后台时会调用AppDelegate的 application:handleEventsForBackgroundURLSession:completionHandler: 方法,app会自动存储session的唯一标识;当程序从后台唤醒的时候,就会以该identifier创建一个background session configuration;
因此,为每一个url session 设定一个唯一标识,对于background session和 target 来说是must be
NSURLSession 的生命周期。苹果提供了两种使用途径,一是利用系统的delegate,另一种就是自定义回调方法了;
那什么时候用Session呢??
1.使用后台会话,而你的应用程序没有运行下载或上传的内容。
2.执行自定义身份验证。
3.执行自定义的SSL证书验证。
4.决定传输是否应该下载到磁盘或显示基于由所述服务器或其他类似标准所返回的MIME类型。
5.通过request body stream(而不是一个NSData对象)上载数据。
6.限制缓存编程。
7.限制HTTP重定向编程。
以下是苹果官网的示例代码:
NSURL *URL = [NSURL URLWithString: TouTiaoInfoList(page)];
//每一个request都保存请求后的Cache, per-app basis, NSURLConnection则以cachePolicy 进行查询
NSURLRequest *theRequest=[NSURLRequest requestWithURL:URL cachePolicy:NSURLRequestUseProtocolCachePolicy
timeoutInterval:60.0];
// 创建一个NSMutableData
_receivedData = [NSMutableData dataWithCapacity: 0];
// create the connection with the request,start loading the data
NSURLConnection *theConnection = [[NSURLConnection alloc] initWithRequest:theRequest delegate:self];
if (!theConnection) {
_receivedData = nil; // Release the receivedData object.
// Inform 失败了声明一下进行处理;
}
// [NSURLConnection sendAsynchronousRequest:theRequest queue:[[NSOperationQueue alloc] init]
// completionHandler:^(NSURLResponse* response, NSData* data, NSError* connectionError){
// NSLog(@"response %@, \n%@", response, data);
// }];
// NSURLCredential *credential = [ NSURLCredential credentialWithUser:@"halo"
// password:@"121212" persistence:NSURLCredentialPersistenceForSession];
//
// NSURLResponse *response = [NSURLResponse alloc];
}
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse {
NSHTTPURLResponse *httpResponse = (NSHTTPURLResponse*)[cachedResponse response];
// Look up the cache policy used in our request
if([connection currentRequest].cachePolicy == NSURLRequestUseProtocolCachePolicy) {
NSDictionary *headers = [httpResponse allHeaderFields];
NSString *cacheControl = [headers valueForKey:@"Cache-Control"];
NSString *expires = [headers valueForKey:@"Expires"];
if((cacheControl == nil) && (expires == nil)) {
NSLog(@"server does not provide expiration information and we are using NSURLRequestUseProtocolCachePolicy");
return nil; // don't cache this
}
}
return cachedResponse;
}
- (void)connection:(NSURLConnection *)connection didFailWithError:(NSError *)error
{
_receivedData = nil;
NSLog(@"Connection failed! Error - %@ %@", [error localizedDescription],
[[error userInfo] objectForKey:NSURLErrorFailingURLStringErrorKey]);
}
- (void)connection:(NSURLConnection *)connection didReceiveData:(NSData *)data
{
// Append the new data to receivedData.
[_receivedData appendData:data];
}
- (void)connection:(NSURLConnection *)connection didReceiveResponse:(NSURLResponse *)response
{
// [_receivedData setLength:0];
}
- (void)connectionDidFinishLoading:(NSURLConnection *)connection
{
NSLog(@"Succeeded! Received %d bytes of data",[_receivedData length]);
connection = nil;
_receivedData = nil;
}
关于AFNetworking 框架的使用; 2.0
2.0 最大的改变就是支持了NSURLSession 的使用,这个是苹果在新的7,0 推出用于替代,10年前的网络请求框架,NSURLConnection;
由于NSURLConnection 是包括了对于会话管理,高速缓存策略,cookie存储和URL协议的大范围的设置,而在NSURLSession中利用particular configuration,
配置请求方式,缓存的方法,从而实现fetch data, and upload or download files
对于AF 来说最大的变化就是对请求内容negotiation and serialisation , 在之前对于请求响应使用的是 AFHTTPRequestOperation 与其子类,对于特殊的请求使用setCompletionBlockWithSuccess:failure: 在2.0 之后所有请求均使用AFURLResponseSerialization; 同时系列化的概念也延伸至request(用来解耦对于AFHTTPClient的依赖) 通过使用 AFURLRequestSerialization;
这两种系列化 只要调两个方法
- (NSURLRequest *)requestBySerializingRequest:(NSURLRequest *)request
withParameters:(NSDictionary *)parameters
error:(NSError *__autoreleasing *)error
- (id)responseObjectForResponse:(NSURLResponse *)response
data:(NSData *)data
error:(NSError *__autoreleasing *)error
对于非常规的request 方法(常规: HTTPMethodsEncodingParametersInURI), AFJSONResponseSerializer 能够自动将request body 进行系列化,对于request的参数可以通过AFPropertyListSerializer
来进行
由于在早期版来中AFHTTPClient 做了太多的事情: 创建请求, 多任务字节流的创建,队列,队列管理,系列化,批队列,以及网络连接检查等;
现在有了对NSURLConnection 和NSURLSession的管理类AFHTTPRequestOperationManager和AFHTTPSessionManager其它功能被细分到serialization, security, and network reachability monitoring.
在2.0之后会对每一个baseURL配置一个网络状态监听;
用法:
HTTPRequest Operation Manager 它封装了http request 和 response 的系列化, 网络状态的监听(具体可以参考apple 网络监听类)
这里特殊说明的是关于文件post 请求做了什么事情以及它与普通的URL表单的编码post请求的区别。 这里重要的区别就是在于:
POST:parameters:constructingBodyWithBlock:success:failure:
这里的文件post如图片,文档的上传等,
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *parameters = @{@"foo": @"bar"};
NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"];
[manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<</b>AFMultipartFormData> formData) {
[formData appendPartWithFileURL:filePath name:@"image" error:nil];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", responseObject);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
而对于NSURLSessionManager 主要是对iOS 6之后出现的NSURLSession 类的封装,NSURLSession类是以配置文件对象, NSURLSessionConfiguration 来初始化生成url 请求。具体关于Session类可以看苹果官网; 最后将网络请求交予一个NSURLSessionDownloadTask
NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration];
NSURL *URL = [NSURL URLWithString:@"http://example.com/download.zip"];
NSURLRequest *request = [NSURLRequest requestWithURL:URL];
NSURLSessionDownloadTask *downloadTask = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
NSURL *documentsDirectoryPath = [NSURL fileURLWithPath:[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject]];
return [documentsDirectoryPath URLByAppendingPathComponent:[response suggestedFilename]];
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(@"File downloaded to: %@", filePath);
}];
[downloadTask resume];