一 AFNetworking基本信息
1. 将AFNetworking导入项目中
注:AFNetWorking使用了ARC ,在不使用ARC项目中使用时,对AFNetWorking的所有.m文件添加“-fobjc-arc”
2. 添加3个类库:Security.framework、MobileCoreServices.framework、SystemConfiguration.framework
3.先编译一下程序,如果这时就有编译错误就在Prefix.pch文件中加入
#import<SystemConfiguration/SystemConfiguration.h>
#import<MobileCoreServices/MobileCoreServices.h>
4.AFN的特性
(1) AFURLConnectionOperation以及他的子类都继承自NSOperation, 可以对他进行 start/cancel/pause/resume 操作,可以获取对应的 NSURLRequest 和 NSURLResponse 数据。支持 NSInputStream/NSOutputStream,提供了 uploadProgress 和 downloadProgress以方便其他使用。
(2) AFNetworking可以将远程媒体数据类型(NSData)转化为可用的格式,比如JSON,XML,图像和plist。
(3)AFHTTPClient提供了一个方便的网络交互接口,包括默认头,身份验证,是否连接到网络,批量处理操作,查询字符串参数序列化,以及多种表单请求
5.AFN与系统的HTTP请求API的对应关系
l AFURLConnectionOperation-NSOperation的子类,负责管理 NSURLConnection 并且实现其 delegate 方法。 l AFHTTPRequestOperation - AFURLConnectionOperation 的子类,用于生成 HTTP 请求,可以区别可接受的和不可接受的状态码及内容类型 l AFHTTPRequestOperationManager - 包装常见 HTTP web 服务操作的类,通过AFHTTPRequestOperation 由 NSURLConnection 支持 |
NSURLConnection
|
l AFURLSessionManager - 创建、管理基于 NSURLSessionConfiguration 对象的NSURLSession 对象的类,也可以管理 session 的数据、下载/上传任务,实现 session 和其相关联的任务的 delegate 方法。 l AFHTTPSessionManager - AFURLSessionManager 的子类,包装常见的 HTTP web 服务操作,通过 AFURLSessionManager 由 NSURLSession 支持。 |
NSURLSession (iOS 7 / Mac OS X 10.9)
|
§ AFHTTPRequestSerializer § AFJSONRequestSerializer § AFPropertyListRequestSerializer |
AFURLRequestSerialization
|
§ AFJSONResponseSerializer § AFXMLParserResponseSerializer § AFXMLDocumentResponseSerializer (Mac OS X) § AFPropertyListResponseSerializer § AFImageResponseSerializer § AFCompoundResponseSerializer |
AFURLResponseSerialization
|
| Additional Functionality |
6.AFN的简单使用
(1)AFHTTPRequestOperation
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: url]];
//创建一个AF的请求队列
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];
//设置请求完成或失败的block
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"Success: %@", operation.responseString);
NSData *resData = [[NSData alloc]initWithData:operation.responseData]; //系统自带JSON解析
NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:resData options:NSJSONReadingMutableLeaves error:nil];
NSLog(@"resultDic:%@",resultDic);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Failure: %@", error);
}];
//开始执行队列中的请求
[operation start];
(2) AFHTTPRequestOperationManager
GET和POST请求(所有的网络请求,均有manager发起 )
要使用常规的AFN网络访问,要特别注意请求的数据的格式,否则很容易请求失败
1. 需要注意的是,默认提交请求的数据是二进制的,返回格式是JSON
2. 请求格式
AFHTTPRequestSerializer 二进制格式
AFJSONRequestSerializer JSON
AFPropertyListRequestSerializer PList(是一种特殊的XML,解析起来相对容易)
3. 返回格式
AFHTTPResponseSerializer 二进制格式
AFJSONResponseSerializer JSON
AFXMLParserResponseSerializer XML,只能返回XMLParser,还需要自己通过代理方法解析
AFXMLDocumentResponseSerializer (Mac OS X)
AFPropertyListResponseSerializer PList
AFImageResponseSerializer Image
AFCompoundResponseSerializer 组合
GET请求AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//请求成功运行success块,请求失败failure块
[manager GET:@"http://www.weather.com.cn/data/sk/101010300.html" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
NSLog(@"请求成功");
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"请求失败:%@",error);
}];
post请求
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *dict = @{@"name": @"zhangsan"};
NSDictionary *dict1 = @{@"name": @"wangwu"};
NSArray *array = @[dict, dict1];
// 设置请求格式
manager.requestSerializer = [AFJSONRequestSerializer serializer];
// 设置返回格式
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:@"要提交数据的链接" parameters:array success:^(AFHTTPRequestOperation
operation, id responseObject) {
NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
NSLog(@"%@", result);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"error: %@",error);
}];
(3) AFHTTPRequestSerializer & AFHTTPResponseSerializer(请求序列化和相应序列化)
//RequestSerializer给manager一个post请求
[[AFHTTPRequestSerializer serializer] requestWithMethod:@"POST" URLString:baseUrl parameters:parameters error:nil];
在AFHTTPRequestOperationManager则不需要实例化AFHTTPRequestSerializer的对象,只要设置 manager.requestSerializer = [AFHTTPRequestSerializerserializer];
7. UIKit 扩展
之前AFNetworking 中的所有 UIKit category 都被保留并增强,还增加了一些新的 category。
AFNetworkActivityIndicatorManager:在请求操作开始、停止加载时,自动开始、停止状态栏上的网络活动指示图标。
UIImageView+AFNetworking:增加了 imageResponseSerializer 属性,可以轻松地让远程加载到 image view 上的图像自动调整大小或应用滤镜。比如,AFCoreImageSerializer可以在 response 的图像显示之前应用 Core Image filter。
UIButton+AFNetworking (新):与 UIImageView+AFNetworking 类似,从远程资源加载image 和 backgroundImage。
UIActivityIndicatorView+AFNetworking (新):根据指定的请求操作和会话任务的状态自动开始、停止 UIActivityIndicatorView。
UIProgressView+AFNetworking (新):自动跟踪某个请求或会话任务的上传/下载进度。
UIWebView+AFNetworking (新): 为加载 URL请求提供了更强大的API,支持进度回调和内容转换。
如何选择AFNetworking版本
首先得下载AFNetworking库文件,下载时得首先弄清楚,你将要开发的软件兼容的最低版本是多少。AFNetworking 2.0或者之后的版本需要xcode5.0版本并且只能为IOS6或更高的手机系统上运行,如果开发MAC程序,那么2.0版本只能在MAC OS X 10.8或者更高的版本上运行。
AFNetworking 2.0的下载地址https://github.com/AFNetworking/AFNetworking
如果你想要兼容IOS5或MAC OS X 10.7,那你需要用最新发布的1.x版本
AFNetworking 1.x的下载地址https://github.com/AFNetworking/AFNetworking/tree/1.x
如果要兼容4.3或者MAC OS X 10.6,需要用最新发布的0.10.x版本
AFNetworking 0.10.xhttps://github.com/AFNetworking/AFNetworking/tree/0.10.x
如何通过URL获取json数据
第一种,利用AFJSONRequestOperation,官方网站上给的例子:
NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 从URL获取json数据
AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary* JSON) {
NSLog(@"获取到的数据为:%@",JSON);
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {
NSLog(@"发生错误!%@",error);
}];
[operation1 start];
第二种方法,利用
AFHTTPRequestOperation
先获取到字符串形式的数据,然后转换成
json
格式,将
NSString
格式的数据转换成
json
数据,利用
IOS5
自带的
json
解析方法:
NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];
NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];
[operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, idresponseObject) {
NSString *html = operation.responseString;
NSData* data=[html dataUsingEncoding:NSUTF8StringEncoding];
id dict=[NSJSONSerialization JSONObjectWithData:data options:0 error:nil];
NSLog(@"获取到的数据为:%@",dict);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"发生错误!%@",error);
}];
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
[queue addOperation:operation];
如果发生
Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x14defc80 {NSUnderlyingError=0x14deea10 "bad URL", NSLocalizedDescription=bad URL
这个错误,请检查
URL
编码格式。有没有进行
stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding
如何通过URL获取图片
异步获取图片,通过队列实现,而且图片会有缓存,在下次请求相同的链接时,系统会自动调用缓存,而不从网上请求数据。
UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 100.0f, 100.0f, 100.0f)]; [imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"]placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]]; [self.view addSubview:imageView];
上面的方法是官方提供的,还有一种方法,
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.scott-sherwood.com/wp-content/uploads/2013/01/scene.png"]];
AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse*response, UIImage *image) {
self.backgroundImageView.image = image;
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {
NSLog(@"Error %@",error);
}];
[operation start];
如果使用第一种 URLWithString : placeholderImage : 会有更多的细节处理,其实实现还是通过 AFImageRequestOperation 处理,可以点击 URLWithString : placeholderImage : 方法进去看一下就一目了然了。所以我觉得还是用第一种好。
如何通过URL获取plist文件
通过url获取plist文件的内容,用的很少,这个方法在官方提供的方法里面没有
NSString *weatherUrl = @"http://www.calinks.com.cn/buick/kls/Buickhousekeeper.plist";
NSURL *url = [NSURL URLWithString:[weatherUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
[AFPropertyListRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/plain"]];
AFPropertyListRequestOperation *operation = [AFPropertyListRequestOperation propertyListRequestOperationWithRequest:request success:^(NSURLRequest *request,NSHTTPURLResponse *response, id propertyList) {
NSLog(@"%@",(NSDictionary *)propertyList);
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, idpropertyList) {
NSLog(@"%@",error);
}];
[operation start];
如何通过URL获取XML数据
xml解析使用AFXMLRequestOperation,需要实现苹果自带的NSXMLParserDelegate委托方法,XML中有一些不需要的协议格式内容,所以就不能像json那样解析,还得实现委托。我之前有想过能否所有的XML链接用一个类处理,而且跟服务端做了沟通,结果很不方便,效果不好。XML大多标签不同,格式也不固定,所以就有问题,使用json就要方便的多。
第一步;在.h文件中加入委托NSXMLParserDelegate
第二步;在.m文件方法中加入代码
NSURL *url = [NSURL URLWithString:@"http://113.106.90.22:5244/sshopinfo"];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
AFXMLRequestOperation *operation =
[AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest*request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {
XMLParser.delegate = self;
[XMLParser setShouldProcessNamespaces:YES];
[XMLParser parse];
}failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser*XMLParser) {
NSLog(@"%@",error);
}];
[operation start];
第三步;在.m文件中实现委托方法
//在文档开始的时候触发
(void)parserDidStartDocument:(NSXMLParser *)parser{
NSLog(@"解析开始!");
}
//解析起始标记
- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary*)attributeDict{
NSLog(@"标记:%@",elementName);
}
//解析文本节点
- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{
NSLog(@"值:%@",string);
}
//解析结束标记
- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{
NSLog(@"结束标记:%@",elementName);
}
//文档结束时触发
-(void) parserDidEndDocument:(NSXMLParser *)parser{
NSLog(@"解析结束!");
}
如何使用AFHTTPClient进行web service操作
AFHTTPClient处理GET 和 POST请求.做网页的朋友们这个方法用的比较多。在要经常调用某个请求时,可以封装,节省资源。
BaseURLString = @"http://www.raywenderlich.com/downloads/weather_sample/";
NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:BaseURLString]];
NSDictionary *parameters = [NSDictionary dictionaryWithObject:@"json" forKey:@"format"];
AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];
[client registerHTTPOperationClass:[AFJSONRequestOperation class]];
[client setDefaultHeader:@"Accept" value:@"text/html"];
[client postPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation*operation, id responseObject) {
NSString* newStr = [[NSString alloc] initWithData:responseObjectencoding:NSUTF8StringEncoding];
NSLog(@"POST请求:%@",newStr);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
[client getPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation*operation, id responseObject) {
NSString* newStr = [[NSString alloc] initWithData:responseObjectencoding:NSUTF8StringEncoding];
NSLog(@"GET请求:%@",newStr);
}failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@",error);
}];
如果需要显示网络活动指示器,可以用下面方法:
[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;
AFNetworking2.5
1.检测网络状态
+ (void)netWorkStatus
{
/**
AFNetworkReachabilityStatusUnknown = -1, // 未知
AFNetworkReachabilityStatusNotReachable = 0, // 无连接
AFNetworkReachabilityStatusReachableViaWWAN = 1, // 3G 花钱
AFNetworkReachabilityStatusReachableViaWiFi = 2, // WiFi
*/
// 如果要检测网络状态的变化,必须用检测管理器的单例的startMonitoring
[[AFNetworkReachabilityManager sharedManager] startMonitoring];
// 检测网络连接的单例,网络变化时的回调方法
[[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
NSLog(@"%ld", status);
}];
}
2.
JSON
方式获取数据
+ (void)JSONDataWithUrl:(NSString *)url success:(void (^)(id json))success fail:(void (^)())fail;
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSDictionary *dict = @{@"format": @"json"};
// 网络访问是异步的,回调是主线程的,因此程序员不用管在主线程更新UI的事情
[manager GET:url parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@", error);
if (fail) {
fail();
}
}];
}
3.xml方式获取数据
+ (void)XMLDataWithUrl:(NSString *)urlStr success:(void (^)(id xml))success fail:(void (^)())fail
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// 返回的数据格式是XML
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
NSDictionary *dict = @{@"format": @"xml"};
// 网络访问是异步的,回调是主线程的,因此程序员不用管在主线程更新UI的事情
[manager GET:urlStr parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@", error);
if (fail) {
fail();
}
}];
}
4.post提交json数据
+ (void)postJSONWithUrl:(NSString *)urlStr parameters:(id)parameters success:(void (^)(id responseObject))success fail:(void (^)())fail
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// 设置请求格式
manager.requestSerializer = [AFJSONRequestSerializer serializer];
// 设置返回格式
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
[manager POST:urlStr parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
// NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"%@", error);
if (fail) {
fail();
}
}];
}
5.下载文件
+ (void)sessionDownloadWithUrl:(NSString *)urlStr success:(void (^)(NSURL *fileURL))success fail:(void (^)())fail
{
NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];
AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:config];
NSString *urlString = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSURL *url = [NSURL URLWithString:urlString];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
NSURLSessionDownloadTask *task = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {
// 指定下载文件保存的路径
// NSLog(@"%@ %@", targetPath, response.suggestedFilename);
// 将下载文件保存在缓存路径中
NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];
NSString *path = [cacheDir stringByAppendingPathComponent:response.suggestedFilename];
// URLWithString返回的是网络的URL,如果使用本地URL,需要注意
// NSURL *fileURL1 = [NSURL URLWithString:path];
NSURL *fileURL = [NSURL fileURLWithPath:path];
// NSLog(@"== %@ |||| %@", fileURL1, fileURL);
if (success) {
success(fileURL);
}
return fileURL;
} completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {
NSLog(@"%@ %@", filePath, error);
if (fail) {
fail();
}
}];
[task resume];
}
6.文件上传-自定义上传文件名
+ (void)postUploadWithUrl:(NSString *)urlStr fileUrl:(NSURL *)fileURL fileName:(NSString *)fileName fileType:(NSString *)fileTye success:(void (^)(id responseObject))success fail:(void (^)())fail
{
// 本地上传给服务器时,没有确定的URL,不好用MD5的方式处理
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//@"http://localhost/demo/upload.php"
[manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"头像1.png" withExtension:nil];
// 要上传保存在服务器中的名称
// 使用时间来作为文件名 2014-04-30 14:20:57.png
// 让不同的用户信息,保存在不同目录中
// NSDateFormatter *formatter = [[NSDateFormatter alloc] init];
// // 设置日期格式
// formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";
// NSString *fileName = [formatter stringFromDate:[NSDate date]];
//@"image/png"
[formData appendPartWithFileURL:fileURL name:@"uploadFile" fileName:fileName mimeType:fileTye error:NULL];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
if (fail) {
fail();
}
}];
}
7.文件上传-随机生成文件名
+ (void)postUploadWithUrl:(NSString *)urlStr fileUrl:(NSURL *)fileURL success:(void (^)(id responseObject))success fail:(void (^)())fail
{
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
// AFHTTPResponseSerializer就是正常的HTTP请求响应结果:NSData
// 当请求的返回数据不是JSON,XML,PList,UIImage之外,使用AFHTTPResponseSerializer
// 例如返回一个html,text...
//
// 实际上就是AFN没有对响应数据做任何处理的情况
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// formData是遵守了AFMultipartFormData的对象
[manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {
// 将本地的文件上传至服务器
// NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"头像1.png" withExtension:nil];
[formData appendPartWithFileURL:fileURL name:@"uploadFile" error:NULL];
} success:^(AFHTTPRequestOperation *operation, id responseObject) {
// NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
//
// NSLog(@"完成 %@", result);
if (success) {
success(responseObject);
}
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"错误 %@", error.localizedDescription);
if (fail) {
fail();
}
}];
}