AFNetworking
简介
- 目前国内开发网络应用使用最多的第三方框架
- 是专为
Mac OS
&iOS
设计的一套网络框架 - 对
NSURLConnection
和NSURLSession
做了封装 - 提供有丰富的 API
- 提供了完善的错误解决方案
- 使用简单
官网地址
https://github.com/AFNetworking/AFNetworking
学习第三方框架的步骤
- 获取框架
$ git clone https://github.com/AFNetworking/AFNetworking.git # 更新框架 $ git pull
- 查看官方文档
- 运行演示程序
- 建立学习分支
分支
是学习第三方框架和入手公司项目的重要手段!
- 编写测试程序
- 少百度,如果实在困难,可以谷歌
数据格式
请求的数据格式
- AFURLRequestSerialization
类型 | 说明 |
---|---|
AFHTTPRequestSerializer | 二进制的,默认的 |
AFJSONRequestSerializer | JSON(POST JSON) RESTful 设计风格需要 |
AFPropertyListRequestSerializer | PList(POST Plist-开发中几乎不用) |
响应数据格式
AFURLResponseSerialization
类型 | 说明 |
---|---|
AFHTTPResponseSerializer | HTTP 二进制的 |
AFJSONResponseSerializer | JSON 默认的 |
AFXMLParserResponseSerializer | XML Parser 解析器 SAX 解析 |
AFXMLDocumentResponseSerializer | (Mac OS X) XML DOM |
AFPropertyListResponseSerializer | PList 几乎不用 |
AFImageResponseSerializer | 图像,不支持 GIF |
AFCompoundResponseSerializer | 组合的 |
数据格式小结
- 大多情况下,都是 JSON,不需要指定
-
XML 格式
- 如果
SAX
解析,需要指定格式mgr.responseSerializer = [AFXMLParserResponseSerializer serializer];
-
然后利用代理方法解析
-
如果 DOM 解析,需要指定格式
mgr.responseSerializer = [AFHTTPResponseSerializer serializer];
- 然后利用第三方框架解析
- 如果
-
图像
- AFN 支持图像缓存,也有对应的分类方法和
SDWebImage
非常像! - 但是:不支持
GIF
- AFN 支持图像缓存,也有对应的分类方法和
提示
- 使用 AFN 时,一定记住输出:
error
- 如果
state code == 200
,就是数据格式错误,针对具体格式进行设置即可
补充
以下连接是移动开发中,常见的 XML 数据格式
http://flash.weather.com.cn/wmaps/xml/china.xml
官方演示程序
AppDelegate
设置缓存
NSURLCache *URLCache = [[NSURLCache alloc] initWithMemoryCapacity:4 * 1024 * 1024 diskCapacity:20 * 1024 * 1024 diskPath:nil]; [NSURLCache setSharedURLCache:URLCache];
设置网络访问标示
[[AFNetworkActivityIndicatorManager sharedManager] setEnabled:YES];
AFAppDotNetAPIClient
-
提供全局网络访问入口
-
.h
@interface AFAppDotNetAPIClient : AFHTTPSessionManager
+ (instancetype)sharedClient;
@end
- .m
static NSString * const AFAppDotNetAPIBaseURLString = @"https://api.app.net/";
@implementation AFAppDotNetAPIClient + (instancetype)sharedClient { static AFAppDotNetAPIClient *_sharedClient = nil; static dispatch_once_t onceToken; dispatch_once(&onceToken, ^{ _sharedClient = [[AFAppDotNetAPIClient alloc] initWithBaseURL:[NSURL URLWithString:AFAppDotNetAPIBaseURLString]]; _sharedClient.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone]; }); return _sharedClient; } @end
小结
- 在
AppDelegate
中设置缓存 - 在
AppDelegate
中设置网络访问指示器 - 继承
AFHTTPSessionManager
创建单例统一管理网络访问 - 单例方法中使用了
BaseURL
,设置后,再访问该服务器,可以直接使用相对路径
代码演练
常规代码演练
- (void)postLogin {
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
NSDictionary *params = @{@"username": @"张三&李四", @"password": @"123"}; [mgr POST:@"http://localhost/login.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"POST Login %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; } - (void)getLogin2 { AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; NSDictionary *params = @{@"username": @"张三&李四", @"password": @"123"}; [mgr GET:@"http://localhost/login.php" parameters:params success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"GET Login %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; } - (void)getLogin1 { AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; [mgr GET:@"http://localhost/login.php?username=zhangsan&password=123" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"%@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; } - (void)getDemo { AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager]; [mgr GET:@"http://localhost/demo.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"%@ %@ %@", responseObject, [responseObject class], [NSThread currentThread]); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"%@", error); }]; }
演练小结
- 程序员不需要知道
URL
,直接使用URL
字符串 - 自动实现
JSON
的反序列化 - 网络访问完成的回调,是在主线程,程序员不需要考虑线程间通讯
URL
的参数可以使用 `字典的形式拼接,程序员不在需要考虑
url` 的格式- 程序员不需要考虑百分号转义
- OC中的百分号转义是有缺陷的,特殊字符例如&+= 用OC的百分号转义就不好使了,这时候需要用到AFN中提供的方法
- 程序员不需要知道
HTTP
方法,只需要挑选单词即可!
XML 解析
SAX 解析
tools.responseSerializer = [AFXMLParserResponseSerializer serializer];
DOM 解析
tools.responseSerializer =[AFHTTPResponseSerializer serializer];
多值参数
NetworkTools *tools = [NetworkTools sharedNetworkTools];
NSDictionary *params = @{@"city": @[@"bj", @"sh", @"gz"]}; [tools GET:@"weather.php" parameters:params success:^(NSURLSessionDataTask *task, id responseObject) { NSLog(@"%@", responseObject); } failure:^(NSURLSessionDataTask *task, NSError *error) { NSLog(@"%@", error); }];
PUT 上传 & 进度跟进
- (void)putupload {
NetworkTools *tools = [NetworkTools sharedNetworkTools];
NSString *urlString = @"http://localhost/uploads/321.png";
NSURL *url = [NSURL URLWithString:urlString]; NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url]; request.HTTPMethod = @"PUT"; NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"001.png" withExtension:nil]; NSProgress *progress = nil; [[tools uploadTaskWithRequest:request fromFile:fileURL progress:&progress completionHandler:^(NSURLResponse *response, id responseObject, NSError *error) { NSLog(@"%@ %@", response, responseObject); }] resume]; // KVO [progress addObserver:self forKeyPath:@"completedUnitCount" options:NSKeyValueObservingOptionNew context:nil]; } - (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context { if ([object isKindOfClass:[NSProgress class]]) { NSProgress *progress = object; NSLog(@"%@ - %@ - %f", progress.localizedDescription, progress.localizedAdditionalDescription, progress.fractionCompleted); } }
网络连接状态监听
[tools.reachabilityManager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"%zd", status);
switch (status) {
case AFNetworkReachabilityStatusNotReachable: NSLog(@"没有连接"); break; case AFNetworkReachabilityStatusReachableViaWiFi: NSLog(@"WI-FI"); break; case AFNetworkReachabilityStatusReachableViaWWAN: NSLog(@"3G"); break; default: NSLog(@"未知"); break; } }]; [tools.reachabilityManager startMonitoring];