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) {

        

    }];

}



________________________________________________________________________________________________


post方法请求

- (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 = [[NSURLallocinitFileURLWithPath: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];
<AFURLRequestSerialization> 请求的数据格式
AFHTTPRequestSerializer HTTP,二进制,默认的
AFJSONRequestSerializer JSON
AFPropertyListRequestSerializer PList


//响应的序列化 

  //设置对服务器返回数据的解析方式:

   1.制定http的序列化器---对应二进制data类型(浏览器返回的html,不能直接使用json来解析,获得data数据后手动解析),万能解析器,其他类型页可以用 --->要 手动解析JSON

    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

     2.//XML的序列化器

    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];

    3.//JSON的序列化器

    manager.responseSerializer = [AFJSONResponseSerializer serializer];


AFN会根据response.MIMEType来判断服务器返回的数据类型,序列化器也要做相应的设置,
默认无@"text/plain",就要设置AFN接受的数据类型:
[AFJSONResponseSerializer serializer].acceptableContentType = [NSSet setWithObjects:@"text/xml",@"text/json",@"text/javaScript",
@"application/json",@"text/plain",@"text/html",nil];//设置AFN接受的数据类型.


=====================
AFNetworking实现单点续传,(暂停,下载)
A. 定义一个全局的 NSURLSessionDownloadTask:下载管理句柄
   由其负责所有的网络操作请求

 

@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(@"解析结束!");

}

====================






=========AFN中的缓存机制=======

AFNetworking实际上利用了两套单独的缓存机制:


AFImagecache : 继承于NSCacheAFNetworking的图片内存缓存的类。

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)];

    }

}

    AFImageCacheNSCache的私有实现,它把所有可访问的UIImage对象存入NSCache中,并控制着UIImage对象应该在何时释放,如果UIImage对象释放的时候你希望去做一些监听操作,你可以实现NSCacheDelegate cache:willEvictObject 代理方法。Matt Thompson已经谦虚的告诉我在AFNetworking2.1版本中可通过setSharedImageCache方法来配置AFImageCache,这里是 AFN2.2.1中的UIImageView+AFNetworking文档。

    

    NSURLCache

    

    AFNetworking使用了NSURLConnection,它利用了iOS原生的缓存机制,并且NSURLCache缓存了服务器返回的NSURLRespone对象。NSURLCacheshareCache方法是默认开启的,你可以利用它来获取每一个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-ControlheaderExpires header存在于服务器返回的HTTP response header中,来用于客户端的缓存工作(前者优先级要高于后者),这里面有很多地方需要注意,Cache-Control可以拥有被定义为类似max-age的参数(在更新响应之前要缓存多长时间), public/private 访问或者是noncache(不缓存响应数据),这里对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。


0 0
原创粉丝点击