简介
:AFNetworking 实际上只是对 NSURLSession 高度地封装, 提供一些简单易用的 API 方便我们在 iOS 开发中发出网络请求并在其上更快地构建网络层组件并提供合理的接口.
注意
:在 iOS9 中,苹果默认全局 HTTPs,如果你要发送不安全的 HTTP 请求,需要在 info.plist 中加入如下键值对才能发出不安全的 HTTP 请求
AFN的结构体
-
NSURLConnection
- AFURLConnectionOperation(被废弃)
- AFHTTPRequestOperation(被废弃)
- AFHTTPRequestOperationManager(封装了常用的 HTTP 方法)(被废弃)
属性
* baseURL :AFN建议开发者针对 AFHTTPRequestOperationManager 自定义个一个单例子类,设置 baseURL, 所有的网络访问,都只使用相对路径即可
* requestSerializer :请求数据格式/默认是二进制的 HTTP
* responseSerializer :响应的数据格式/默认是 JSON 格式
* operationQueue
* reachabilityManager :网络连接管理器方法
* manager :方便创建管理器的类方法
* HTTPRequestOperationWithRequest :在访问服务器时,如果要告诉服务器一些附加信息,都需要在 Request 中设置
* GET
* POST
-
NSURLSession
AFURLSessionManager
-
AFHTTPSessionManager(封装了常用的HTTP方法)
- GET
- POST
- UIKit + AFNetworking 分类
- NSProgress:利用KVO
-
半自动的序列化&反序列化的功能
- AFURLRequestSerialization:请求的数据格式/默认是二进制的
- AFURLResponseSerialization:响应的数据格式/默认是JSON格式
附加功能
HTTPS
AFSecurityPolicy
网络检测
对苹果的网络连接检测做了一个封装
AFNetworkReachabilityManager
1.AFN发送GET和POST请求
由于经常需要大部分界面都需要用到post或者get发送网络请求,故可自己封装一个发送请求的工具类
2.AFN实现文件下载
- 1.创建会话管理者
- 2.下载文件
- 3.执行Task
//1.创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.下载文件
/**
request:请求对象
progress: 进度回调 downloadProgress
destination:回调(目标位置)注意:有返回值(NSURL)
targetPath: 临时文件路径
response:响应头信息
completionHandler:下载完成后的回调
filePath:最终的文件路径
*/
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://120.25.226.186:32812/resources/videos/minion_01.mp4"]];
NSURLSessionDownloadTask *download =[manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
//监听下载进度
//completedUnitCount 已经下载的数据大小
//totalUnitCount 文件数据的中大小
NSLog(@"%f",1.0*downloadProgress.completedUnitCount/downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSLog(@"targetPath:%@",targetPath);
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)lastObject]stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"targetPath:%@",targetPath);
NSLog(@"fullPath:%@",fullPath);
return [NSURL URLWithString:fullPath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@",filePath); //filePath与上面的fullPath路径是一样的
}];
//3.执行Task
[download resume];
3.AFN实现文件上传
//1.创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.上传文件
/**
* POST:请求路径
* parameters:请求参数
* constructingBodyWithBlock:处理要上传的文件数据
* progress:进度
* success:成功回调
* failure:失败回调
*/
[manager POST:@"http://120.25.226.186:32812/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
// [formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/love/Desktop/gitBooksnip/Snip20160815_1.png"] name:@"file" error:nil];
//使用formData来拼接数据
/**
* name :服务器规定的
* fileName:该文件上传到服务器以什么名称保存
*/
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/love/Desktop/gitBooksnip/Snip20160815_1.png"] name:@"file" fileName:@"123.png" mimeType:@"image/png" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"%f",1.0 * uploadProgress.completedUnitCount/uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"task:%@ 上传成功:%@",task,responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"上传失败:%@",error);
}];
4.AFN序列化
1.AFN内部默认吧服务器响应的数据当做json来解析,如果服务器返回的不是json格式的数据,那么将会报错,此时需要设置AFN的解析响应信息的方式
-
AFXMLParserResponseSerializer
//xml -
AFHTTPResponseSerializer
//默认二进制响应数据 -
AFJSONResponseSerializer
//json
2.AFN只提供了3种数据格式,如图:
,若服务器返回给我们的数据格式不太一致(开发者工具Content-Type:text/xml),那么这种情况也有可能请求不成功。解决方法:
1) 直接在源代码中修改,添加相应的Content-Type
2) 拿到这个属性,添加到它的集合中
-(void)srializer
{
//1.创建请求管理者,内部基于NSURLSession
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
/* 知识点1:设置AFN采用什么样的方式来解析服务器返回的数据*/
//如果返回的是XML,那么告诉AFN,响应的时候使用XML的方式解析
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
//如果返回的就是二进制数据,那么采用默认二进制的方式来解析数据
//manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//采用JSON的方式来解析数据
//manager.responseSerializer = [AFJSONResponseSerializer serializer];
/*知识点2 告诉AFN,再序列化服务器返回的数据的时候,支持此种类型
[AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
//2.把所有的请求参数通过字典的方式来装载,GET方法内部会自动把所有的键值对取出以&符号拼接并最后用?符号连接在请求路径后面
NSDictionary *dict = @{
@"username":@"223",
@"pwd":@"ewr",
@"type":@"XML"
};
//3.发送GET请求
[manager GET:@"http://120.25.226.186:32812/login" parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
//4.请求成功的回调block
NSLog(@"%@",[responseObject class]);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
//5.请求失败的回调,可以打印error的值查看错误信息
NSLog(@"%@",error);
}];
}
5.AFN检测网络状态
- 可以使用AFN框架中的AFNetworkReachabilityManager来监听网络状态的改变,也可以利用苹果提供的Reachability来监听
//使用AFN框架来检测网络状态的改变
-(void)AFNReachability
{
//1.创建网络监听管理者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
//2.监听网络状态的改变
/*
AFNetworkReachabilityStatusUnknown = 未知
AFNetworkReachabilityStatusNotReachable = 没有网络
AFNetworkReachabilityStatusReachableViaWWAN = 3G
AFNetworkReachabilityStatusReachableViaWiFi = WIFI
*/
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"没有网络");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
default:
break;
}
}];
//3.开始监听
[manager startMonitoring];
}
------------------------------------------------------------
//使用苹果提供的Reachability来检测网络状态,如果要持续监听网络状态的概念,需要结合通知一起使用。
//提供下载地址:https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip
-(void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
//1.注册一个通知
[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];
//2.拿到一个对象,然后调用开始监听方法
Reachability *r = [Reachability reachabilityForInternetConnection];
[r startNotifier];
//持有该对象,不要让该对象释放掉
self.r = r;
}
//当控制器释放的时候,移除通知的监听
-(void)dealloc
{
[[NSNotificationCenter defaultCenter] removeObserver:self];
}
-(void)networkChange
{
//获取当前网络的状态
if ([Reachability reachabilityForInternetConnection].currentReachabilityStatus == ReachableViaWWAN)
{
NSLog(@"当前网络状态为3G");
return;
}
if ([Reachability reachabilityForLocalWiFi].currentReachabilityStatus == ReachableViaWiFi)
{
NSLog(@"当前网络状态为wifi");
return;
}
NSLog(@"当前没有网络");
}