AFN框架(二)的使用和有关序列化器的问题--缓存机制------
来源:互联网 发布:淘宝直播端口 编辑:程序博客网 时间:2024/05/01 05:15
AFHTTPRequestOperationManager:内部封装的是 NSUrlConnection,网络请求管理类,用来负责发送网络请求,是使用最多的一个类.
AFHTTPSessionManager :内部封装的是 NSUrlSession,网络请求管理类,用来负责发送网络请求,
一些主要的工具类:
AFNetworkReachabilityManager.h :实时监测网络状态改变的管理类.
AFSecurityPolicy.h :HTTPS 需要使用.
AFURLRequestSerialization: 数据解析的时候会使用.
AFHTTPRequestSerializer: 万能解析器/对服务器返回的数据不做任务处理.
AFJSONResponseSerializer: JSON解析器.
AFXMLParserResponseSerializer: XML解析器.
AFHTTPRequestOperationManager对NSURLConnection的封装.
AFHTTPSessionManager对NSURLSession的封装
1.创建管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
2.设置管理者的数据解析类型,默认为 json 格式的解析,可手动修改为其他类型,如 XML:
manager.responseSerializer = [AFXMLParserResponseSerializer serializer]
3.1 首先要明确发送的是什么类型的请求(GET/POST/HEAD...)
3.2 AFN 3.0之后的网络接口相比之前的网络接口多了一个参数:网络进度.
参数:
1. urlString: 网络接口地址.
2. parameters: 参数字典.key:服务器接收普通参数的key值,value就是参数内容.
3. progress: 网络进度
4. success: 成功回调
5. failure: 失败回调
3.3 AFN根据 response.MIMEType 来判断服务器返回数据的类型. 如果类型不匹配,但是又是JSON数据,解决方案:
1.改变解析器类型为:万能解析器 ---> 手动解析JSON
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
2.改变判断条件的类型,以使类型匹配,acceptableContentTypes默认情况下无 text/plain 类型
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/plain",nil];
===========
AFHTTPRequestOperationManager
get请求
- (void)get{
//1获取manager
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManagermanager];
/*
1.访问的地址
2.参数
3.成功的回调
4.失败的回调
*/
[manager GET:@"http://127.0.0.1/demo.json"parameters:nilsuccess:^(AFHTTPRequestOperation*_Nonnull operation, id _Nonnull responseObject) {
//responseObject返回的数据,已经自动的json反序列化
NSLog(@"%@",[responseObjectclass]);
} failure:^(AFHTTPRequestOperation *_Nullable operation,NSError * _Nonnull error) {
}];
}
//get请求带参数
- (void)get2{
//1获取manager
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManagermanager];
/*
1.访问的地址
2.参数
3.成功的回调
4.失败的回调
*/
//?username=111&password=111
[manager GET:@"http://127.0.0.1/login.PHP"parameters:@{@"username":@"11",@"password":@"222"}success:^(AFHTTPRequestOperation*_Nonnull operation,id _Nonnull responseObject) {
//responseObject返回的数据,已经自动的json反序列化
NSLog(@"%@",responseObject);
} failure:^(AFHTTPRequestOperation *_Nullable operation,NSError * _Nonnull error) {
}];
}
//post带参数请求
- (void)post{
//1获取manager
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManagermanager];
/*
1.访问的地址
2.参数
3.成功的回调
4.失败的回调
*/
//?username=111&password=111
[manager POST:@"http://127.0.0.1/login.php"parameters:@{@"username":@"11",@"password":@"222"}success:^(AFHTTPRequestOperation*_Nonnull operation,id _Nonnull responseObject) {
//responseObject返回的数据,已经自动的json反序列化
NSLog(@"%@",responseObject);
} failure:^(AFHTTPRequestOperation *_Nullable operation,NSError * _Nonnull error) {
}];
}
_________________________________________________________
//post请求上传文件
-(void)uploadfiles{
AFHTTPRequestOperationManager *manager =[AFHTTPRequestOperationManagermanager];
/*
1.访问的地址
2.参数
3.constructingBodyWithBlock 构建请求体,把要发送的数据放到里面
4.成功的回调
5.失败的回调
*/
[manager POST:@"http://127.0.0.1/upload/upload-m.php"parameters:@{@"username":@"itcast"}constructingBodyWithBlock:^(id<AFMultipartFormData> _NonnullformData) {
NSURL *fileURL = [[NSBundlemainBundle]URLForResource:@"1.JPG"withExtension:nil];
[formData appendPartWithFileURL:fileURL name:@"userfile[]"error:NULL];//这里的name要和服务器的name一样.fileURLname是本地文件,这个方法多次使用,可以实现多文件上传(改一下URL即可).
} success:^(AFHTTPRequestOperation *_Nonnull operation, id _Nonnull responseObject) {
NSLog(@"%@",responseObject);
} failure:^(AFHTTPRequestOperation *_Nullable operation,NSError * _Nonnull error) {
}];
}
________________________________________________________________________________________________
________________________________________________________________________________________________
________________________________________________________________________________________________
AFHTTPSessionManager----------以前的方法
get方法请求
- (void)get{
//1.manager
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
[manager GET:@"http://127.0.0.1/demo.json"parameters:nilsuccess:^(NSURLSessionDataTask*_Nonnull task, id _Nonnull responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask *_Nullable task, NSError*_Nonnull error) {
}];
}
________________________________________________________________________________________________
- (void)post{
//1.manager
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
[manager POST:@"http://127.0.0.1/login.php"parameters:@{@"username":@"11",@"password":@"222"}success:^(NSURLSessionDataTask*_Nonnull task,id _Nonnull responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask *_Nullable task, NSError*_Nonnull error) {
}];
}
________________________________________________________________________________________________
//downloadTaskWithRequest:下载文件,带进度
-(void)downloadFile{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://127.0.0.1/1.mp4"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
/*
1.请求
2.进度
3.下载的目的地需要自己制定下载路径 通过block返回
4.完成回调
*/
NSProgress *progress;
[[manager downloadTaskWithRequest:requst progress:&progress destination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath,NSURLResponse * _Nonnull response) {
//存到temp目录中,这是设置下载的路径
NSString *path = [NSTemporaryDirectory()stringByAppendingPathComponent:response.suggestedFilename];
NSURL *url = [[NSURLalloc] initFileURLWithPath:path];
return url;
} completionHandler:^(NSURLResponse *_Nonnull response, NSURL* _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@",filePath);
}] resume];
//输出进度 KVO添加观察者
/*
1.谁观察
2.观察的key
3.选项
*/
[progress addObserver:selfforKeyPath:@"fractionCompleted"options:NSKeyValueObservingOptionNewcontext:nil];
}
-(void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context{
//观察方法
/*
1.要观察的key
2.要观察的对象
3.新值的变化
4.其他参数
*/
//判断监控的对象类型
if([object isKindOfClass:[NSProgressclass]]){
NSProgress *progress = object;
//打印进度
// NSLog(@"%f",progress.fractionCompleted);
NSLog(@"%@",progress.localizedDescription);
}
}
_____
________________________________________________________________________________________________
AFHTTPSessionManager----------更新后的方法
#import "ViewController.h"
#import <AFNetworking.h>
@interfaceViewController ()
@property(nonatomic,strong)NSURLSessionDownloadTask *downloadTask;
@property(nonatomic,strong)NSData *resumeData;
@property(nonatomic,strong)AFURLSessionManager *manager;
@end
@implementation ViewController
- (void)viewDidLoad {
[superviewDidLoad];
[selfget];
}
//0--get--------
@interface NetworkTools : AFHTTPSessionManager
+ (instancetype)sharedTools {
staticCZNetworkTools *tools;
staticdispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//
NSURL *baseURL = [NSURLURLWithString:@"http://c.m.163.com/nc/"];
NSURLSessionConfiguration *config = [NSURLSessionConfigurationdefaultSessionConfiguration];
//设置请求的超时时长
config.timeoutIntervalForRequest =15;
tools = [[selfalloc]initWithBaseURL:baseURLsessionConfiguration:config];
});
return tools;
-(void)get{
[[CZNetworkTools sharedTools] GET:baseURL后面的路径 parameters:nil progress:^(NSProgress *_Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask *_Nonnull task,id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask *_Nullable task, NSError *_Nonnull error) {
}];
}
//----1---get
- (void)get{
//1.manager
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
//2.待超时时间
NSURLSessionConfiguration *config = [NSURLSessionConfigurationdefaultSessionConfiguration];
config.timeoutIntervalForRequest = 50.0;
AFHTTPSessionManager *manager = [[AFHTTPSessionManageralloc]initWithSessionConfiguration:config];
manager.securityPolicy = [AFSecurityPolicypolicyWithPinningMode:AFSSLPinningModeNone];//安全策略 AFSSLPinningModeCertificate(校验证书)
manager.securityPolicy.allowInvalidCertificates =YES;//客户端是否信任非法证书
manager.securityPolicy.validatesDomainName =NO;//不验证证书的域名
manager.responseSerializer.acceptableContentTypes=[NSSetsetWithObjects:@"application/json",@"text/json",@"text/javascript",@"text/html",@"text/xml",@"text/plain; charset=utf-8",nil];
manager.responseSerializer = [AFHTTPResponseSerializerserializer];
//序列化器的类型
// manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializerserializer];
[manager GET:@"http://121.43.187.220"parameters:nilprogress:^(NSProgress *_Nonnull downloadProgress) {
} success:^(NSURLSessionDataTask *_Nonnull task,id _Nullable responseObject) {
//如果后台的数据是标准的JSON格式,得到的数据就是字典,可以直接使用;只有最上面的节点是数组和字典才能用JSON解析;
//如果后台的数据不是标准的JSON格式,就需要用下面的方法自己解析;
===== responset返回的是十六进制的数据: //先序列化成字符串
NSString *getLoginstr=[NSJSONSerialization
JSONObjectWithData:responseObject
options:NSJSONReadingAllowFragmentserror:&err];
NSData* jsonData = [getLoginstr
dataUsingEncoding:NSUTF8StringEncoding];
NSArray *array =[NSJSONSerialization
JSONObjectWithData:jsonData
options:kNilOptionserror:&err];
====response返回如下数据:
cards = "[{\"cvn\":\"123\",\"idno\":\"341126197709218366\",\"name\":\"\U53e4\U53e4\U60d1\U60d1\",\"expiry\":\"1117\",\"card_no\":\"6221558812340000\",\"last_time\":\"2017-09-15 15:04:25\",\"last_amount\":1},{\"cvn\":\"123\",\"idno\":\"341126197709218366\",\"name\":\"\U53e4\U53e4\U60d1\U60d1\",\"expiry\":\"1111\",\"card_no\":\"622262226222\"}]";
NSData *data=[responseObject[@"cards"]dataUsingEncoding:NSUTF8StringEncoding];
NSArray *dict=[NSJSONSerializationJSONObjectWithData:data
options:NSJSONReadingMutableLeaveserror:nil];
//=======如果请求的是网页数据:
NSString *str=[[NSStringalloc]initWithData:responseObjectencoding:NSUTF8StringEncoding];//网页二进制数据转换成字符串
NSLog(@"---responseStr---%@",str);
NSData *data=[str dataUsingEncoding:NSUTF8StringEncoding];
NSDictionary *responseObject=[NSJSONSerialization JSONObjectWithData:data
options:NSJSONReadingAllowFragments error:nil];
} failure:^(NSURLSessionDataTask *_Nullable task,NSError * _Nonnull error) {
}];
}
//-------2----post
-(void)postWithThreeBlock{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
manager.securityPolicy = [AFSecurityPolicypolicyWithPinningMode:AFSSLPinningModeNone];//安全策略
manager.securityPolicy.allowInvalidCertificates =YES;
//序列化器的类型
// manager.responseSerializer = [AFJSONResponseSerializer serializer];
manager.responseSerializer = [AFHTTPResponseSerializerserializer];
******accept是请求头的设置,表示服务器可以接受的数据格式(MIME);
contentType是响应头的设置,向服务器请求的数据类型,表示服务端返回的数据格式,也就是客户端可以接受的数据格式;
//下列请求头参数根据你自己的后台接口要求来设置[manager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Accept"];[manager.requestSerializer setValue:@"application/json;charset=UTF-8" forHTTPHeaderField:@"Content-Type"];[manager.requestSerializer setValue:@"keep-alive" forHTTPHeaderField:@"Connection"];[manager.requestSerializer setValue:@"zh-cn" forHTTPHeaderField:@"language"];//如果报接受类型不一致请替换一致text/html或别的manager.responseSerializer.acceptableContentTypes = nil;
设置向请求内容的类型
[manager.requestSerializer setValue:@"application/json;charset=utf-8"forHTTPHeaderField:@"Content-Type"];//这个和
设置请求内容的长度
[manager.requestSerializer setValue:[NSStringstringWithFormat:@"%ld", (unsignedlong)[jsonStr length]] forHTTPHeaderField:@"Content-Length"];
设置请求的编码类型
[manager.requestSerializer setValue:@"gzip"forHTTPHeaderField:@"Content-Encoding"];
//可以序列化的类型------向服务器请求的数据类型,服务器返回的数据类型
manager.responseSerializer.acceptableContentTypes=[NSSetsetWithObjects:@"application/json",@"text/json",@"text/javascript",@"text/html",@"text/xml",@"text/plain; charset=utf-8",nil];
[manager.requestSerializer setValue:@"text/html;charset=utf-8"
forHTTPHeaderField:@"Content-Type"]; //请求的URL所用的编码类型;如果不设置,默认的是json
[manager.requestSerializer
setValue:@"application/json" forHTTPHeaderField:@"Accept"];//浏览器或客户端可以接受的数据类型,
[manager POST:@"http://121.43.187.220"parameters:nilprogress:^(NSProgress *_Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask *_Nonnull task,id _Nullable responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask *_Nullable task,NSError * _Nonnull error) {
}];
}
//-----3-----post
-(void)postWithFourBlock{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
[manager POST:@"http://121.43.187.220"parameters:nilconstructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
//拼接二进制文件数据 第一个参数:要上传文件的url路径
第二个参数:服务器要求的参数名称
第三个参数:这个文件上传到服务器之后叫什么名称
第四个参数:文件的mimetype类型
第五个参数:错误信息
UIImage *image=[UIImageimageNamed:@"test01"];
NSData* imageData =UIImagePNGRepresentation(image);
NSString* sname = [NSStringstringWithFormat:@"img_file[%@]" ,@"1"];
NSString *fileName=[[NSBundlemainBundle]pathForResource:@"test01.png"ofType:nil];//本地文件路径
// //上传图片,以文件流的格式//这里的name要和服务器的name一样.fileName是本地文件路径,这个方法多次使用,可以实现多文件上传(改一下fileName即可)
[formData appendPartWithFileData:imageDataname:snamefileName:fileNamemimeType:@"image/png"];
//**************
// formData appendPartWithFileURL:<#(nonnull NSURL *)#> name:<#(nonnull NSString *)#> fileName:<#(nonnull NSString *)#> mimeType:<#(nonnull NSString *)#> error:<#(NSError *__autoreleasing _Nullable * _Nullable)#>
//****************
// formData appendPartWithFormData:<#(nonnull NSData *)#> name:<#(nonnull NSString *)#>
//**************
// formData appendPartWithFileURL:<#(nonnull NSURL *)#> name:<#(nonnull NSString *)#> error:<#(NSError *__autoreleasing _Nullable * _Nullable)#>
//****************
//*****************
// formData appendPartWithInputStream:<#(nullable NSInputStream *)#> name:<#(nonnull NSString *)#> fileName:<#(nonnull NSString *)#> length:<#(int64_t)#> mimeType:<#(nonnull NSString *)#>
//******************
} progress:^(NSProgress *_Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask *_Nonnull task,id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask *_Nullable task,NSError * _Nonnull error) {
}];
}
//------4------dataTask
-(void)datataskNormal{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
[manager dataTaskWithRequest:requstcompletionHandler:^(NSURLResponse *_Nonnull response, id _Nullable responseObject,NSError *_Nullable error) {
}];
}
//-----5-----dataTask
-(void)dataTaskWithupProgressAndDownProgress{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
[manager dataTaskWithRequest:requstuploadProgress:^(NSProgress *_Nonnull uploadProgress) {
} downloadProgress:^(NSProgress *_Nonnull downloadProgress) {
} completionHandler:^(NSURLResponse *_Nonnull response,id _Nullable responseObject,NSError *_Nullable error) {
}];
}
//----6------upload
-(void)uploadTaskNormal{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
[manager uploadTaskWithStreamedRequest:requstprogress:^(NSProgress *_Nonnull uploadProgress) {
} completionHandler:^(NSURLResponse *_Nonnull response,id _Nullable responseObject,NSError *_Nullable error) {
}];
}
//-----7-----upload
-(void)uploadTaskWithFromData{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
UIImage *image=[UIImageimageNamed:@"test01"];
NSData* imageData =UIImagePNGRepresentation(image);
[manager uploadTaskWithRequest:requstfromData:imageDataprogress:^(NSProgress *_Nonnull uploadProgress) {
} completionHandler:^(NSURLResponse *_Nonnull response,id _Nullable responseObject,NSError *_Nullable error) {
}];
}
//-----8-----upload
-(void)uploadWIithfromFile{
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
NSString *fileName=[[NSBundlemainBundle]pathForResource:@"test01.png"ofType:nil];
NSURL *fileUrl=[NSURLURLWithString:fileName];
[manager uploadTaskWithRequest:requstfromFile:fileUrlprogress:^(NSProgress *_Nonnull uploadProgress) {
} completionHandler:^(NSURLResponse *_Nonnull response,id _Nullable responseObject,NSError *_Nullable error) {
}];
}
//-------9------download
-(void)download{
NSURLSessionConfiguration * configuration = [NSURLSessionConfigurationdefaultSessionConfiguration]; //配置有三种模式,后台,缓存,鉴权安全
//*****AFURLSessionManager是AFHTTPSessionManager的父类******
AFURLSessionManager * manager = [[AFURLSessionManageralloc]initWithSessionConfiguration:configuration];
self.manager=manager;
NSURL *url =[NSURLURLWithString:@"http://121.43.187.220"];
NSURLRequest *requst = [NSURLRequestrequestWithURL:url];
NSURLSessionDownloadTask *downloadTask= [managerdownloadTaskWithRequest:requstprogress:^(NSProgress *_Nonnull downloadProgress) {
} destination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath, NSURLResponse * _Nonnull response) {
//这里要返回一个NSURL,其实就是文件的位置路径
NSString * path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)lastObject];
//使用建议的路径suggestedFilename
path = [path stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"%@",path);
return [NSURLfileURLWithPath:path];//转化为文件路径---下载到了这个地方
} completionHandler:^(NSURLResponse *_Nonnull response,NSURL * _Nullable filePath,NSError *_Nullable error) {
//如果下载的是压缩包的话,可以在这里进行解压
NSLog(@"----%@---%ld---%@",error.domain,error.code,error);
//下载成功
if (error ==nil) {
// completion(YES,@"下载完成",[filePath path]);
}else{//下载失败的时候,只列举判断了两种错误状态码
NSString * message =nil;
if (error.code == - 1005) {
message = @"网络异常";
}elseif (error.code == -1001){
message = @"请求超时";
}else{
message = @"未知错误";
}
// completion(NO,message,nil);
}
}];
self.downloadTask=downloadTask;
}
//取消下载
- (void)pauseClicked {
[self.downloadTaskcancelByProducingResumeData:^(NSData *_Nullable resumeData) {
self.resumeData = resumeData;//记录当前下载的数据
self.downloadTask =nil;//吧任务置为空
}];
}
//继续下载
- (void)continueClicked{
[selfdownloadTaskWithResumeData];
self.resumeData =nil;//吧保存的数据置为空
}
//10----download
-(void)downloadTaskWithResumeData{
[self.managerdownloadTaskWithResumeData:self.resumeDataprogress:^(NSProgress *_Nonnull downloadProgress) {
} destination:^NSURL *_Nonnull(NSURL *_Nonnull targetPath, NSURLResponse * _Nonnull response) {
//这里要返回一个NSURL,其实就是文件的位置路径
NSString * path = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory,NSUserDomainMask,YES)lastObject];
//使用建议的路径suggestedFilename
path = [path stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"%@",path);
return [NSURLfileURLWithPath:path];//转化为文件路径---下载到了这个地方
} completionHandler:^(NSURLResponse *_Nonnull response,NSURL * _Nullable filePath,NSError *_Nullable error) {
}];
}
@end
***********************
________________________________________________________________________________________________
序列化器
AFHTTPSessionManager *manager = [AFHTTPSessionManagermanager];
//请求的序列化:
请求的数据格式(一般都是
HTTP
二进制数据,RESTful设计风格要求 POST JSON)self.requestSerializer = [AFHTTPRequestSerializer serializer];
AFHTTPRequestSerializer HTTP,二进制,默认的
AFJSONRequestSerializer JSON
AFPropertyListRequestSerializer PList
//响应的序列化
//设置对服务器返回数据的解析方式:
1.制定http的序列化器---对应二进制data类型(浏览器返回的是html,不能直接使用json来解析,获得data数据后手动解析),万能解析器,其他类型页可以用 --->要 手动解析JSON
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
manager.responseSerializer = [AFJSONResponseSerializer serializer];
@interface ViewController (){ // 下载句柄 NSURLSessionDownloadTask *_downloadTask;}
.h文件#import <UIKit/UIKit.h>@interface ViewController : UIViewController// 下载文件显示@property (weak, nonatomic) IBOutlet UIImageView *imageView;// 下载进度条显示@property (weak, nonatomic) IBOutlet UIProgressView *progressView;@end.m文件@interface ViewController (){ // 下载句柄 NSURLSessionDownloadTask *_downloadTask;}
2.利用AFN实现文件下载操作细节
- (void)downFileFromServer{ //远程地址 NSURL *URL = [NSURL URLWithString:@"http://www.baidu.com/img/bdlogo.png"]; //默认配置 NSURLSessionConfiguration *configuration = [NSURLSessionConfiguration defaultSessionConfiguration]; //AFN3.0+基于封住URLSession的句柄 AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:configuration]; //请求 NSURLRequest *request = [NSURLRequest requestWithURL:URL]; //下载Task操作 _downloadTask = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) { // @property int64_t totalUnitCount; 需要下载文件的总大小 // @property int64_t completedUnitCount; 当前已经下载的大小 // 给Progress添加监听 KVO NSLog(@"%f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount); // 回到主队列刷新UI dispatch_async(dispatch_get_main_queue(), ^{ // 设置进度条的百分比 self.progressView.progress = 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount; }); } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) { //- block的返回值, 要求返回一个URL, 返回的这个URL就是文件的位置的路径 NSString *cachesPath = [NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject]; NSString *path = [cachesPath stringByAppendingPathComponent:response.suggestedFilename]; return [NSURL fileURLWithPath:path]; } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) { //设置下载完成操作 // filePath就是你下载文件的位置,你可以解压,也可以直接拿来使用 NSString *imgFilePath = [filePath path];// 将NSURL转成NSString UIImage *img = [UIImage imageWithContentsOfFile:imgFilePath]; self.imageView.image = img; }];}
3.关于暂停和继续
- (IBAction)stopDownloadBtnClick:(id)sender { //暂停下载 [_downloadTask suspend];}- (IBAction)startDownloadBtnClick:(id)sender { //开始下载 [_downloadTask resume];}
4.检测网络状态--优化用户体验
- (void)viewDidLoad { [super viewDidLoad]; //网络监控句柄 AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager]; //要监控网络连接状态,必须要先调用单例的startMonitoring方法 [manager startMonitoring]; [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { //status: //AFNetworkReachabilityStatusUnknown = -1, 未知 //AFNetworkReachabilityStatusNotReachable = 0, 未连接 //AFNetworkReachabilityStatusReachableViaWWAN = 1, 3G //AFNetworkReachabilityStatusReachableViaWiFi = 2, 无线连接 NSLog(@"%d", status); }]; //准备从远程下载文件. -> 请点击下面开始按钮启动下载任务 [self downFileFromServer];}
________________________________________________________________________________________________
AFHTTPSessionManager----------XML解析
如何通过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(@"解析结束!");
}
====================AFNetworking实际上利用了两套单独的缓存机制:
AFImagecache : 继承于NSCache,AFNetworking的图片内存缓存的类。
NSURLCache : NSURLConnection的默认缓存机制,用于存储NSURLResponse对象:一个默认缓存在内存,并且可以通过一些配置操作可以持久缓存到磁盘的类。
AFImageCache是如何工作的?
AFImageCache属于UIImageView+AFNetworking的一部分,继承于NSCache,以URL(从NSURLRequest对象中获取)字符串作为key值来存储UIImage对象。 AFImageCache的定义如下:(这里我们声明了一个2M内存、100M磁盘空间的NSURLCache对象。)
@interface AFImageCache : NSCache// singleton instantiation :
+ (id )sharedImageCache {
static AFImageCache *_af_defaultImageCache =nil;
staticdispatch_once_t oncePredicate;
dispatch_once(&oncePredicate, ^{
_af_defaultImageCache = [[AFImageCache alloc] init];
// clears out cache on memory warning :
[[NSNotificationCenterdefaultCenter]addObserverForName:UIApplicationDidReceiveMemoryWarningNotificationobject:nilqueue:[NSOperationQueuemainQueue]usingBlock:^(NSNotification *__unused notification) {
[_af_defaultImageCache removeAllObjects];
}];
});
// key from [[NSURLRequest URL] absoluteString] :
staticinline NSString * AFImageCacheKeyFromURLRequest(NSURLRequest *request) {
return [[request URL] absoluteString];
}
@implementation AFImageCache
// write to cache if proper policy on NSURLRequest :
- (UIImage *)cachedImageForRequest:(NSURLRequest *)request {
switch ([request cachePolicy]) {
case NSURLRequestReloadIgnoringCacheData:
case NSURLRequestReloadIgnoringLocalAndRemoteCacheData:
returnnil;
default:
break;
}
return [self objectForKey:AFImageCacheKeyFromURLRequest(request)];
}
// read from cache :
- (void)cacheImage:(UIImage *)image
forRequest:(NSURLRequest *)request {
if (image && request) {
[self setObject:image forKey:AFImageCacheKeyFromURLRequest(request)];
}
}
AFImageCache是NSCache的私有实现,它把所有可访问的UIImage对象存入NSCache中,并控制着UIImage对象应该在何时释放,如果UIImage对象释放的时候你希望去做一些监听操作,你可以实现NSCacheDelegate的 cache:willEvictObject 代理方法。Matt Thompson已经谦虚的告诉我在AFNetworking2.1版本中可通过setSharedImageCache方法来配置AFImageCache,这里是 AFN2.2.1中的UIImageView+AFNetworking文档。
NSURLCache
AFNetworking使用了NSURLConnection,它利用了iOS原生的缓存机制,并且NSURLCache缓存了服务器返回的NSURLRespone对象。NSURLCache的shareCache方法是默认开启的,你可以利用它来获取每一个NSURLConnection对象的URL内容。让人不爽的是,它的默认配置是缓存到内存而且并没有写入到磁盘。为了tame the beast(驯服野兽?不太懂),增加可持续性,你可以在AppDelegate中简单地声明一个共享的NSURLCache对象,像这样:
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:2 * 1024 * 1024
diskCapacity:100 * 1024 * 1024
diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
设置NSURLRequest对象的缓存策略
NSURLCache 将对每一个NSURLRequest对象遵守缓存策略(NSURLRequestCachePolicy),策略如下所示:
- NSURLRequestUseProtocolCachePolicy 默认的缓存策略,对特定的URL请求使用网络协议中实现的缓存逻辑
- NSURLRequestReloadIgnoringLocalCacheData 忽略本地缓存,重新请请求
- NSURLRequestReloadIgnoringLocalAndRemoteCacheData忽略本地和远程缓存,重新请求
- NSURLRequestReturnCacheDataElseLoad 有缓存则从中加载,如果没有则去请求
- NSURLRequestReturnCacheDataDontLoad 无网络状态下不去请求,一直加载本地缓存数据无论其是否存在
- NSURLRequestReloadRevalidatingCacheData 默从原始地址确认缓存数据的合法性之后,缓存数据才可使用,否则请求原始地址
======用NSURLCache缓存数据到磁盘=====
Cache-Control HTTP Header
Cache-Controlheader或Expires header存在于服务器返回的HTTP response header中,来用于客户端的缓存工作(前者优先级要高于后者),这里面有很多地方需要注意,Cache-Control可以拥有被定义为类似max-age的参数(在更新响应之前要缓存多长时间), public/private 访问或者是non-cache(不缓存响应数据),这里对HTTP cache headers进行了很好的介绍。
继承并控制NSURLCache
如果你想跳过Cache-Control,并且想要自己来制定规则读写一个带有NSURLResponse对象的NSURLCache,你可以继承NSURLCache。下面有个例子,使用 CACHE_EXPIRES来判断在获取源数据之前对缓存数据保留多长时间.(感谢 Mattt Thompson的回复)
@interface CustomURLCache : NSURLCache
static NSString *const CustomURLCacheExpirationKey =@"CustomURLCacheExpiration";
staticNSTimeIntervalconst CustomURLCacheExpirationInterval = 600;
@implementation CustomURLCache
+ (instancetype)standardURLCache {
static CustomURLCache *_standardURLCache =nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
_standardURLCache = [[CustomURLCache alloc]
initWithMemoryCapacity:(2 * 1024 * 1024)
diskCapacity:(100 * 1024 * 1024)
diskPath:nil];
}
return _standardURLCache;
}
#pragma mark - NSURLCache
- (NSCachedURLResponse *)cachedResponseForRequest:(NSURLRequest *)request {
NSCachedURLResponse *cachedResponse = [super cachedResponseForRequest:request];
if (cachedResponse) {
NSDate* cacheDate = cachedResponse.userInfo[CustomURLCacheExpirationKey];
NSDate* cacheExpirationDate = [cacheDate dateByAddingTimeInterval:CustomURLCacheExpirationInterval];
if ([cacheExpirationDate compare:[NSDate date]] == NSOrderedAscending) {
[self removeCachedResponseForRequest:request];
returnnil;
}
}
}
return cachedResponse;
}
- (void)storeCachedResponse:(NSCachedURLResponse *)cachedResponse
forRequest:(NSURLRequest *)request
{
NSMutableDictionary *userInfo = [NSMutableDictionarydictionaryWithDictionary:cachedResponse.userInfo];
userInfo[CustomURLCacheExpirationKey] = [NSDate date];
NSCachedURLResponse *modifiedCachedResponse = [[NSCachedURLResponsealloc]initWithResponse:cachedResponse.responsedata:cachedResponse.datauserInfo:userInfostoragePolicy:cachedResponse.storagePolicy];
[super storeCachedResponse:modifiedCachedResponse forRequest:request];
}
@end
现在你有了属于自己的NSURLCache的子类,不要忘了在AppDelegate中初始化并且使用它。
在缓存之前重写NSURLResponse
-connection:willCacheResponse 代理方法是在被缓存之前用于截断和编辑由NSURLConnection创建的NSURLCacheResponse的地方。对NSURLCacheResponse进行处理并返回一个可变的拷贝对象(代码来自NSHipster blog)
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse {
NSMutableDictionary *mutableUserInfo = [[cachedResponse userInfo] mutableCopy];
NSMutableData *mutableData = [[cachedResponse data] mutableCopy];
NSURLCacheStoragePolicy storagePolicy = NSURLCacheStorageAllowedInMemoryOnly;
// ...
return [[NSCachedURLResponse alloc] initWithResponse:[cachedResponse response]
data:mutableData
userInfo:mutableUserInfo
storagePolicy:storagePolicy];
}
// If you do not wish to cache the NSURLCachedResponse, just return nil from the delegate function:
- (NSCachedURLResponse *)connection:(NSURLConnection *)connection
willCacheResponse:(NSCachedURLResponse *)cachedResponse {
returnnil;
}
禁用NSURLCache
可以禁用NSURLCache,只需要将内存和磁盘空间设置为0就行了.
NSURLCache *sharedCache = [[NSURLCache alloc] initWithMemoryCapacity:0
diskCapacity:0
diskPath:nil];
[NSURLCache setSharedURLCache:sharedCache];
AFNetworking利用的系统自有类存储,我们可以修改其源代码:
[[NSURLCache sharedURLCache] removeAllCachedResponses];
这一句代码是清除所有的URL缓存Response。
- AFN框架(二)的使用和有关序列化器的问题--缓存机制------
- AFN 的使用问题
- 有关hibernate的缓存机制
- 使用AFN出现的问题以及解决方法
- AFN的坑--NSCachedURLResponse缓存
- AFN图片的本地缓存
- Android的缓存机制(java序列化)
- iOS AFN 做缓存(如何简单的做缓存)
- NSURLConnection/AFN 缓存机制
- 41.AFN的使用和收藏工具
- 有关EGOImageView缓存的问题
- AFN的使用
- AFN的 基本使用
- AFN的使用
- AFN的使用方式
- AFN的使用
- AFN-的基本使用
- 有关测试序列的问题
- 啊啊啊
- 求最大字段和
- Linux安装配置Mysql及优化(一)
- Node.js连接mysql数据库
- [算法练习]选择排序的C语言实现
- AFN框架(二)的使用和有关序列化器的问题--缓存机制------
- Netty源码(一):Netty中的Buffer
- [PAT][GPLT][CCCC]L1-020.帅到没朋友
- 级数求和 C# lanmda写法
- Bootstrap 图标
- (反射方法)写一个将一个String类型的json经过base64加密后解密转化成javaBean的工具类
- Hadoop 从 hdfs 中拷出文件权限不够
- [参考]Hadoop集群完全分布式模式环境部署
- Oracle数据库的查询之基本查询(一)