今天和大家一起来学习一下AFNetworking的基本使用,有疏忽的地方,还望各位不吝赐教。
一、AFNetworking的基本使用
1、控制器代码
#import "ViewController.h"
#import
@interface ViewController ()
@end
/*
* 在开发中进行二次封装可以简化步骤
*/
@implementation ViewController
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self download];
}
// 下载文件
- (void)download{
// 1、创建文件管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 确定URL
NSURL *url = [NSURL URLWithString:@""];
// 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 下载文件
/*
* 第一个参数:请求对象
* 第二个参数:progress 进度回调
* 第三个参数:destination 回调(目标位置)
有返回值
targetPath:临时文件路径
response:响应头信息
* 第三个参数:completionHandler 下载完成之后的回调
filePath:最终的文件路径
error :错误信息
*/
NSURLSessionDownloadTask * task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
NSLog(@"%f",1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
NSString *fullPath = [[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:response.suggestedFilename];
NSLog(@"%@",fullPath);
return [NSURL fileURLWithPath:fullPath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@",filePath);
}];
[task resume];
}
// 上传文件
- (void)upload{
// 创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 发送请求上传文件 然后就依据NSURLSession类似的方式上传
[manager uploadTaskWithRequest:nil fromData:nil progress:^(NSProgress * _Nonnull uploadProgress) {
} completionHandler:^(NSURLResponse * _Nonnull response, id _Nullable responseObject, NSError * _Nullable error) {
}];
}
// 利用POST的方式上传文件
- (void)upload2{
// 创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 发送post请求上传文件
/*
第一个参数:请求路径
第二个参数:字典(非文件参数) 可以不传
第三个参数:constructingBodyWithBlock 处理要上传的文件数据
第四个参数:进度回调
第五个参数:成功回调 responseObject:响应体信息
第六个参数:失败回调
*/
[manager POST:@"" parameters:nil constructingBodyWithBlock:^(id _Nonnull formData) {
//使用formData来拼接数据
/*
第一个参数:二进制数据 要上传的文件参数
第二个参数:服务器规定的
第三个参数:该文件上传到服务器以什么名称保存
*/
//[formData appendPartWithFileData:imageData name:@"file" fileName:@"xxxx.png" mimeType:@"image/png"];
//[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/xiaomage/Desktop/Snip.png"] name:@"file" fileName:@"123.png" mimeType:@"image/png" error:nil];
[formData appendPartWithFileURL:[NSURL fileURLWithPath:@"/Users/xiaomage/Desktop/Snip.png"] name:@"file" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
2、请求类封装
#import
#import "AFNetworking.h"
@interface YYHttpTool : NSObject
/**
* 发送一个GET请求
*
* @param url 请求路径
* @param params 请求参数
* @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
* @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
*/
+ (void)get:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;
/**
* 发送一个POST请求
*
* @param url 请求路径
* @param params 请求参数
* @param success 请求成功后的回调(请将请求成功后想做的事情写到这个block中)
* @param failure 请求失败后的回调(请将请求失败后想做的事情写到这个block中)
*/
+ (NSURLSessionDataTask *)post:(NSString *)url params:(NSDictionary *)params success:(void(^)(id responseObj))success failure:(void(^)(NSError *error))failure;
@end
#import "YYHttpTool.h"
@implementation YYHttpTool
+(void)get:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
//1.获得请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
//2.发送Get请求
[mgr GET:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
}
+(NSURLSessionDataTask *)post:(NSString *)url params:(NSDictionary *)params success:(void (^)(id))success failure:(void (^)(NSError *))failure
{
//1.获得请求管理者
AFHTTPSessionManager *mgr = [AFHTTPSessionManager manager];
NSURLSessionDataTask *dataTask = [mgr POST:url parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
if (success) {
success(responseObject);
}
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (failure) {
failure(error);
}
}];
return dataTask;
}
@end
3、NSMutableURLRequest+XMGUpload 分类 上传的时候会使用 具体参照《iOS网络请求策略——NSURLSession的基本使用》中上传操作
#import
@interface NSMutableURLRequest (XMGUpload)
/**
* 生成单文件上传的 multipart/form-data 请求
*
* @param URL 上传地址
* @param fileURL 要上传的本地文件地址
* @param name 服务器参数名称
*
* @return multipart/form-data POST 请求,保存到服务器的文件名与本地的文件名一致
*/
+ (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL name:(NSString *)name;
/**
* 生成单文件上传的 multipart/form-data 请求
*
* @param URL 上传地址
* @param fileURL 要上传的本地文件地址
* @param fileName 要保存在服务器上的文件名
* @param name 服务器参数名称
*
* @return multipart/form-data POST 请求
*/
+ (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL fileName:(NSString *)fileName name:(NSString *)name;
/**
* 生成多文件上传的 multipart/form-data 请求
*
* @param URL 上传地址
* @param fileURLs 要上传的本地文件地址 数组
* @param name 服务器参数名称
*
* @return multipart/form-data POST 请求,保存到服务器的文件名与本地的文件名一致
*/
+ (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs name:(NSString *)name;
/**
* 生成多文件上传的 multipart/form-data 请求
*
* @param URL 上传地址
* @param fileURLs 要上传的本地文件地址 数组
* @param fileNames 要保存在服务器上的文件名 数组
* @param name 服务器参数名称
*
* @return multipart/form-data POST 请求
*/
+ (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs fileNames:(NSArray *)fileNames name:(NSString *)name;
@end
#import "NSMutableURLRequest+XMGUpload.h"
@implementation NSMutableURLRequest (XMGUpload)
+ (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL name:(NSString *)name {
return [self requestWithURL:URL fileURLs:@[fileURL] name:name];
}
+ (instancetype)requestWithURL:(NSURL *)URL fileURL:(NSURL *)fileURL fileName:(NSString *)fileName name:(NSString *)name {
return [self requestWithURL:URL fileURLs:@[fileURL] fileNames:@[fileName] name:name];
}
+ (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs name:(NSString *)name {
NSMutableArray *fileNames = [NSMutableArray arrayWithCapacity:fileURLs.count];
[fileURLs enumerateObjectsUsingBlock:^(NSURL *fileURL, NSUInteger idx, BOOL *stop) {
[fileNames addObject:fileURL.path.lastPathComponent];
}];
return [self requestWithURL:URL fileURLs:fileURLs fileNames:fileNames name:name];
}
+ (instancetype)requestWithURL:(NSURL *)URL fileURLs:(NSArray *)fileURLs fileNames:(NSArray *)fileNames name:(NSString *)name {
NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:URL];
request.HTTPMethod = @"POST";
NSMutableData *data = [NSMutableData data];
NSString *boundary = multipartFormBoundary();
if (fileURLs.count > 1) {
name = [name stringByAppendingString:@"[]"];
}
[fileURLs enumerateObjectsUsingBlock:^(NSURL *fileURL, NSUInteger idx, BOOL *stop) {
NSString *bodyStr = [NSString stringWithFormat:@"\n--%@\n", boundary];
[data appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]];
NSString *fileName = fileNames[idx];
bodyStr = [NSString stringWithFormat:@"Content-Disposition: form-data; name=\"%@\"; filename=\"%@\" \n", name, fileName];
[data appendData:[bodyStr dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[@"Content-Type: application/octet-stream\n\n" dataUsingEncoding:NSUTF8StringEncoding]];
[data appendData:[NSData dataWithContentsOfURL:fileURL]];
[data appendData:[@"\n" dataUsingEncoding:NSUTF8StringEncoding]];
}];
NSString *tailStr = [NSString stringWithFormat:@"--%@--\n", boundary];
[data appendData:[tailStr dataUsingEncoding:NSUTF8StringEncoding]];
request.HTTPBody = data;
NSString *headerString = [NSString stringWithFormat:@"multipart/form-data; boundary=%@", boundary];
[request setValue:headerString forHTTPHeaderField:@"Content-Type"];
return request;
}
static NSString * multipartFormBoundary() {
return [NSString stringWithFormat:@"Boundary+%08X%08X", arc4random(), arc4random()];
}
@end
二、XML解析(GET请求为例)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self get];
}
- (void)get{
// 创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 返回的是xml的数据,修改AFN的解析方案
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
// 如果返回的数据既不是xml也不是json那么应该修改解析方案 比如图片
// manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// 如果请求的是网站(html)
manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"text/html", nil];
NSDictionary *params = @{
@"type":@"XML"
};
// 发送get请求和发送post请求的方式相同,AFN把请求路径和参数进行了分离
[manager GET:@"" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
// NSLog(@"%@",responseObject);
// 创建解析器
NSXMLParser *parser = (NSXMLParser *)responseObject;
// 设置代理
parser.delegate = self;
// 开始解析
[parser parse];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
if (error) {
NSLog(@"error--%@",error);
}
}];
}
- (void)parser:(NSXMLParser *)parser didStartElement:(nonnull NSString *)elementName namespaceURI:(nullable NSString *)namespaceURI qualifiedName:(nullable NSString *)qName attributes:(nonnull NSDictionary *)attributeDict{
NSLog(@"%@--%@",elementName,attributeDict);
}
三、网络状态监测
// 检测网络状态
- (void)kvoStatus{
// 获得一个网络状态管理者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager manager];
// 监听网络状态改变
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
/*
AFNetworkReachabilityStatusUnknown = -1,未知
AFNetworkReachabilityStatusNotReachable = 0,没有网络
AFNetworkReachabilityStatusReachableViaWWAN = 1,蜂窝网络
AFNetworkReachabilityStatusReachableViaWiFi = 2,wifi
*/
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"AFNetworkReachabilityStatusUnknown");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"AFNetworkReachabilityStatusNotReachable");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"AFNetworkReachabilityStatusReachableViaWWAN");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"AFNetworkReachabilityStatusReachableViaWiFi");
break;
default:
break;
}
}];
// 开始监听
[manager stopMonitoring];
}
四、https请求的处理(GET请求为例)
- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{
[self get];
}
- (void)get{
// 创建会话管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 对于解析方式修改 https请求
manager.responseSerializer = [AFHTTPResponseSerializer serializer];
// 设置证书的处理方式 接收无效的证书
manager.securityPolicy.allowInvalidCertificates = YES;
// 设置对域名验证为无效
manager.securityPolicy.validatesDomainName = NO;
NSDictionary *params = @{
@"username":@"123",
@"pwd":@"123",
@"type":@"JSON"
};
// 发送get请求和发送post请求的方式相同,AFN把请求路径和参数进行了分离
[manager GET:@"" parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
五、https简介
/**
* https简单说明
HTTPS(全称:Hyper Text Transfer Protocol over Secure Socket Layer),是以安全为目标的HTTP通道,简单讲是HTTP的安全版。
即HTTP下加入SSL层,HTTPS的安全基础是SSL,因此加密的详细内容就需要SSL。 它是一个URI scheme(抽象标识符体系),句法类同http:体系。用于安全的HTTP数据传输。
https:URL表明它使用了HTTP,但HTTPS存在不同于HTTP的默认端口及一个加密/身份验证层(在HTTP与TCP之间)。
2.HTTPS和HTTP的区别主要为以下四点:
一、https协议需要到ca申请证书,一般免费证书很少,需要交费。
二、http是超文本传输协议,信息是明文传输,https 则是具有安全性的ssl加密传输协议。
三、http和https使用的是完全不同的连接方式,用的端口也不一样,前者是80,后者是443。
四、http的连接很简单,是无状态的;HTTPS协议是由SSL+HTTP协议构建的可进行加密传输、身份认证的网络协议,比http协议安全。
3.简单说明
1)HTTPS的主要思想是在不安全的网络上创建一安全信道,并可在使用适当的加密包和服务器证书可被验证且可被信任时,对窃听和中间人攻击提供合理的保护。
2)HTTPS的信任继承基于预先安装在浏览器中的证书颁发机构(如VeriSign、Microsoft等)(意即“我信任证书颁发机构告诉我应该信任的”)。
3)因此,一个到某网站的HTTPS连接可被信任,如果服务器搭建自己的https 也就是说采用自认证的方式来建立https信道,这样一般在客户端是不被信任的。
4)所以我们一般在浏览器访问一些https站点的时候会有一个提示,问你是否继续。
*/
- (void)https{
// 确定URL
NSURL *url = [NSURL URLWithString:@""];
// 创建请求对象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 创建会话对象
NSURLSession *session = [NSURLSession sessionWithConfiguration:[NSURLSessionConfiguration defaultSessionConfiguration] delegate:self delegateQueue:[NSOperationQueue mainQueue]];
// 创建任务
NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {
}];
// 开启任务
[task resume];
}
// 对于大型的网站并不会去质询,因为证书是强制安装的,数据可以直接拿到
- (void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler{
if (![challenge.protectionSpace.authenticationMethod isEqualToString:@"NSURLAuthenticationMethodServerTrust"]) {
return;
}
NSLog(@"%@",challenge.protectionSpace);
/*
NSURLSessionAuthChallengeDisposition 如何处理证书
NSURLSessionAuthChallengeUseCredential = 0, 使用该证书 安装证书
NSURLSessionAuthChallengePerformDefaultHandling = 1,默认采用方式 忽略
NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2, 证书被忽略 请求被取消
NSURLSessionAuthChallengeRejectProtectionSpace = 3, 拒绝安装
*/
// 创建身份信息
NSURLCredential *credential = [[NSURLCredential alloc] initWithTrust:challenge.protectionSpace.serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential,credential);
}