AFNetworking下載地址:https://github.com/AFNetworking/AFNetworking
1.發(fā)送GET請(qǐng)求
第一個(gè)參數(shù):NSString類(lèi)型的請(qǐng)求路徑,AFN內(nèi)部會(huì)自動(dòng)將該路徑包裝為一個(gè)url并創(chuàng)建請(qǐng)求對(duì)象
第二個(gè)參數(shù):請(qǐng)求參數(shù),此處為nil
第三個(gè)參數(shù):進(jìn)度回調(diào),此處為nil
第四個(gè)參數(shù):請(qǐng)求成功之后回調(diào)Block
第五個(gè)參數(shù):請(qǐng)求失敗回調(diào)Block
- (void)get
{
//1.創(chuàng)建會(huì)話(huà)管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.發(fā)送GET請(qǐng)求
[manager GET:URL parameters:nil progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"請(qǐng)求成功---%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"請(qǐng)求失敗---%@",error);
}];
}
2.發(fā)送POST請(qǐng)求
第一個(gè)參數(shù):NSString類(lèi)型的請(qǐng)求路徑,AFN內(nèi)部會(huì)自動(dòng)將該路徑包裝為一個(gè)url并創(chuàng)建請(qǐng)求對(duì)象
第二個(gè)參數(shù):請(qǐng)求參數(shù),以字典的方式傳遞,AFN內(nèi)部會(huì)判斷當(dāng)前是POST請(qǐng)求還是GET請(qǐng)求,以選擇直接拼接還是轉(zhuǎn)換為NSData放到請(qǐng)求體中傳遞
第三個(gè)參數(shù):進(jìn)度回調(diào) 此處為nil
第四個(gè)參數(shù):請(qǐng)求成功之后回調(diào)Block
第五個(gè)參數(shù):請(qǐng)求失敗回調(diào)Block
-(void)post
{
//1.創(chuàng)建會(huì)話(huà)管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.創(chuàng)建參數(shù)
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"BaoBao" forKey:@"Name"];
[dict setObject:@"123" forKey:@"passward"];
//3.發(fā)送POST請(qǐng)求
[manager POST:URL parameters:dict progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//注意:responseObject:請(qǐng)求成功返回的響應(yīng)結(jié)果(AFN內(nèi)部已經(jīng)把響應(yīng)體轉(zhuǎn)換為OC對(duì)象,通常是字典或數(shù)組)
NSLog(@"請(qǐng)求成功---%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"請(qǐng)求失敗---%@",error);
}];
}
3.文件下載
第一個(gè)參數(shù):請(qǐng)求對(duì)象
第二個(gè)參數(shù):進(jìn)度回調(diào)
downloadProgress.completedUnitCount :已經(jīng)下載的數(shù)據(jù)
downloadProgress.totalUnitCount:數(shù)據(jù)的總大小
第三個(gè)參數(shù):destination回調(diào),該block需要返回值(NSURL類(lèi)型)
targetPath:文件的臨時(shí)保存路徑
response:響應(yīng)頭信息
第四個(gè)參數(shù):completionHandler請(qǐng)求完成后回調(diào)
*response:響應(yīng)頭信息
filePath:文件的保存路徑,即destination回調(diào)的返回值
error:錯(cuò)誤信息*
-(void)download
{
//1.創(chuàng)建會(huì)話(huà)管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.創(chuàng)建請(qǐng)求對(duì)象
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"文件"]];
//3.創(chuàng)建下載Task
NSURLSessionDownloadTask *downloadTask = [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(@"%@\n%@",targetPath,fullPath);
return [NSURL fileURLWithPath:fullPath];
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
NSLog(@"%@",filePath);
}];
//4.執(zhí)行Task
[downloadTask resume];
}
4.文件上傳
文件上傳拼接數(shù)據(jù)方式
/*
第一個(gè)參數(shù):要上傳的文件二進(jìn)制數(shù)據(jù)
第二個(gè)參數(shù):文件參數(shù)對(duì)應(yīng)的參數(shù)名稱(chēng),此處為file是該臺(tái)服務(wù)器規(guī)定的
第三個(gè)參數(shù):該文件上傳到服務(wù)后以什么名稱(chēng)保存
第四個(gè)參數(shù):該文件的MIMeType類(lèi)型
*/
(1) [formData appendPartWithFileData:data name:@"file" fileName:@"Image.png" mimeType:@"application/octet-stream"];
/*
第一個(gè)參數(shù):要上傳的文件的URL路徑
第二個(gè)參數(shù):文件參數(shù)對(duì)應(yīng)的參數(shù)名稱(chēng),此處為file是該臺(tái)服務(wù)器規(guī)定的
第三個(gè)參數(shù):該文件上傳到服務(wù)后以什么名稱(chēng)保存
第四個(gè)參數(shù):該文件的MIMeType類(lèi)型
第五個(gè)參數(shù):錯(cuò)誤信息,傳地址
*/
(2) [formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"Image2.png" mimeType:@"application/octet-stream" error:nil];
/*
第一個(gè)參數(shù):要上傳的文件的URL路徑
第二個(gè)參數(shù):文件參數(shù)對(duì)應(yīng)的參數(shù)名稱(chēng),此處為file
第三個(gè)參數(shù):錯(cuò)誤信息
*/
(3) [formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
第一個(gè)參數(shù):請(qǐng)求路徑(NSString類(lèi)型)
第二個(gè)參數(shù):非文件參數(shù),以字典的方式傳遞
第三個(gè)參數(shù):constructingBodyWithBlock 在該回調(diào)中拼接文件參數(shù)
第四個(gè)參數(shù):progress 進(jìn)度回調(diào)
uploadProgress.completedUnitCount:已經(jīng)上傳的數(shù)據(jù)大小
uploadProgress.totalUnitCount:數(shù)據(jù)的總大小
第五個(gè)參數(shù):success 請(qǐng)求成功的回調(diào)
task:上傳Task
responseObject:服務(wù)器返回的響應(yīng)體信息
第六個(gè)參數(shù):failure 請(qǐng)求失敗的回調(diào)
task:上傳Task
error:錯(cuò)誤信息
-(void)upload
{
//1.創(chuàng)建會(huì)話(huà)管理者
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//2.處理參數(shù)(非文件參數(shù))
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"BaoBao" forKey:@"name"];
//3.發(fā)送請(qǐng)求上傳文件
[manager POST:URL parameters:dict constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
UIImage *image = [UIImage imageNamed:@"Image3"];
NSData *imageData = UIImagePNGRepresentation(image);
//在該block中拼接要上傳的文件參數(shù)
[formData appendPartWithFileData:imageData name:@"file" fileName:@"Image5.png" mimeType:@"image/png"];
//[formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"Image7.png" mimeType:@"image/png" error:nil];
//[formData appendPartWithFileURL:fileUrl name:@"file" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
NSLog(@"%f",1.0 * uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSLog(@"請(qǐng)求成功----%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
NSLog(@"請(qǐng)求失敗----%@",error);
}];
}
5.序列化處理
- AFN它內(nèi)部默認(rèn)把服務(wù)器響應(yīng)的數(shù)據(jù)當(dāng)做json來(lái)進(jìn)行解析,所以如果服務(wù)器返回給我的不是JSON數(shù)據(jù)那么請(qǐng)求報(bào)錯(cuò),這個(gè)時(shí)候需要設(shè)置AFN對(duì)響應(yīng)信息的解析方式。AFN提供了三種解析響應(yīng)信息的方式,分別是:
1)AFXMLParserResponseSerializer----XML
2)AFHTTPResponseSerializer---------默認(rèn)二進(jìn)制響應(yīng)數(shù)據(jù)
3)AFJSONResponseSerializer---------JSON
- 服務(wù)器返回給我們的數(shù)據(jù)格式不太一致(開(kāi)發(fā)者工具Content-Type:text/xml),那么這種情況也有可能請(qǐng)求不成功。解決方法:
1) 直接在源代碼中修改,添加相應(yīng)的Content-Type
2) 拿到這個(gè)屬性,添加到它的集合中
-(void)srializer
{
//1.創(chuàng)建請(qǐng)求管理者,內(nèi)部基于NSURLSession
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//如果返回的是XML,那么告訴AFN,響應(yīng)的時(shí)候使用XML的方式解析
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
//如果返回的就是二進(jìn)制數(shù)據(jù),那么采用默認(rèn)二進(jìn)制的方式來(lái)解析數(shù)據(jù)
//manager.responseSerializer = [AFHTTPResponseSerializer serializer];
//采用JSON的方式來(lái)解析數(shù)據(jù)
//manager.responseSerializer = [AFJSONResponseSerializer serializer];
//告訴AFN,再序列化服務(wù)器返回的數(shù)據(jù)的時(shí)候,支持此種類(lèi)型
[AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/xml"];
//2.把所有的請(qǐng)求參數(shù)通過(guò)字典的方式來(lái)裝載,GET方法內(nèi)部會(huì)自動(dòng)把所有的鍵值對(duì)取出以&符號(hào)拼接并最后用?符號(hào)連接在請(qǐng)求路徑后面
NSMutableDictionary *dict = [NSMutableDictionary dictionary];
[dict setObject:@"BaoBao" forKey:@"name"];
[dict setObject:@"passward" forKey:@"123"];
[dict setObject:@"XML" forKey:@"type"];
//3.發(fā)送GET請(qǐng)求
[manager GET:URL parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id _Nonnull responseObject) {
//4.請(qǐng)求成功的回調(diào)block
NSLog(@"%@",[responseObject class]);
} failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {
//5.請(qǐng)求失敗的回調(diào),可以打印error的值查看錯(cuò)誤信息
NSLog(@"%@",error);
}];
}
6.監(jiān)測(cè)網(wǎng)絡(luò)狀態(tài)
說(shuō)明:可以使用AFN框架中的AFNetworkReachabilityManager來(lái)監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài)的改變,也可以利用蘋(píng)果提供的Reachability來(lái)監(jiān)聽(tīng)。
-(void)AFNReachability
{
//1.創(chuàng)建網(wǎng)絡(luò)監(jiān)聽(tīng)管理者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
//2.監(jiān)聽(tīng)網(wǎng)絡(luò)狀態(tài)的改變
/*
AFNetworkReachabilityStatusUnknown = 未知
AFNetworkReachabilityStatusNotReachable = 無(wú)網(wǎng)絡(luò)
AFNetworkReachabilityStatusReachableViaWWAN = 3G 4G
AFNetworkReachabilityStatusReachableViaWiFi = WIFI
*/
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"無(wú)網(wǎng)絡(luò)");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"3G,4G");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WIFI");
break;
default:
break;
}
}];
//3.開(kāi)始監(jiān)聽(tīng)
[manager startMonitoring];
}
7.單例
在開(kāi)發(fā)的過(guò)程中可以創(chuàng)建一個(gè)工具類(lèi),繼承自我們的AFN中的請(qǐng)求管理者,在控制器發(fā)送請(qǐng)求的代碼使用自己封裝的工具類(lèi)。該工具類(lèi)一般提供一個(gè)單例方法,在該方法中會(huì)設(shè)置一個(gè)基本的請(qǐng)求路徑。該方法通常還會(huì)提供對(duì)GET或POST請(qǐng)求的封裝。在外面的時(shí)候通過(guò)該工具類(lèi)來(lái)發(fā)送請(qǐng)求
+ (instancetype)shareNetworkTools
{
static NetworkTools *instance;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//注意: BaseURL中一定要以/結(jié)尾
instance = [[self alloc] initWithBaseURL:[NSURL URLWithString:BaseURL]];
});
return instance;
}
8.HTTPS請(qǐng)求
(1)證書(shū)轉(zhuǎn)換
進(jìn)到證書(shū)路徑,執(zhí)行 openssl x509 -in 證書(shū).crt -out 證書(shū).cer -outform der
語(yǔ)句,這樣就可以得到cer類(lèi)型的證書(shū)了。雙擊,導(dǎo)入電腦。
(2)證書(shū)放入工程
a.可以直接把轉(zhuǎn)換好的cer文件拖動(dòng)到工程中。
b.可以在鑰匙串內(nèi),找到你導(dǎo)入的證書(shū),單擊右鍵,導(dǎo)出項(xiàng)目,就可以導(dǎo)出.cer文件的證書(shū)了
(3)配置Info.plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
(4)使用系統(tǒng)類(lèi)請(qǐng)求HTTPS
如果AFNetworking版本為2.x,使用NSURLConnection設(shè)置支持https
- (void)connection:(NSURLConnection *)connection willSendRequestForAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge{
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// 告訴服務(wù)器,客戶(hù)端信任證書(shū)
// 創(chuàng)建憑據(jù)對(duì)象
NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
// 告訴服務(wù)器信任證書(shū)
[challenge.sender useCredential:credntial forAuthenticationChallenge:challenge];
}
}
NSURLSession設(shè)置支持https
- (void)URLSession:(NSURLSession *)session task:(NSURLSessionTask *)task didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition disposition, NSURLCredential * __nullable credential))completionHandler {
// 判斷是否是信任服務(wù)器證書(shū)
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust) {
// 告訴服務(wù)器,客戶(hù)端信任證書(shū)
// 創(chuàng)建憑據(jù)對(duì)象
NSURLCredential *credntial = [NSURLCredential credentialForTrust:challenge.protectionSpace.serverTrust];
// 通過(guò)completionHandler告訴服務(wù)器信任證書(shū)
completionHandler(NSURLSessionAuthChallengeUseCredential,credntial);
}
}
(5)使用AFNetworking 2.x版本請(qǐng)求HTTPS
a.校驗(yàn)證書(shū)
// 初始化單例類(lèi)
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
mgr.securityPolicy.SSLPinningMode = AFSSLPinningModeCertificate;
// 設(shè)置證書(shū)模式
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
mgr.securityPolicy.pinnedCertificates = [[NSArray alloc] initWithObjects:cerData, nil];
// 客戶(hù)端是否信任非法證書(shū)
mgr.securityPolicy.allowInvalidCertificates = YES;
// 是否在證書(shū)域字段中驗(yàn)證域名
[mgr.securityPolicy setValidatesDomainName:NO];
b.不校驗(yàn)證書(shū)
// 初始化單例類(lèi)
AFHTTPRequestOperationManager *mgr = [AFHTTPRequestOperationManager manager];
mgr.securityPolicy.SSLPinningMode = AFSSLPinningModeCertificate;
// 設(shè)置非校驗(yàn)證書(shū)模式
mgr.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
mgr.securityPolicy.allowInvalidCertificates = YES;
[mgr.securityPolicy setValidatesDomainName:NO];
(6)使用AFNetworking 3.x版本請(qǐng)求HTTPS
a.校驗(yàn)證書(shū)
// 初始化單例類(lèi)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.securityPolicy.SSLPinningMode = AFSSLPinningModeCertificate;
// 設(shè)置證書(shū)模式
NSString * cerPath = [[NSBundle mainBundle] pathForResource:@"xxx" ofType:@"cer"];
NSData * cerData = [NSData dataWithContentsOfFile:cerPath];
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate withPinnedCertificates:[[NSSet alloc] initWithObjects:cerData, nil]];
// 客戶(hù)端是否信任非法證書(shū)
mgr.securityPolicy.allowInvalidCertificates = YES;
// 是否在證書(shū)域字段中驗(yàn)證域名
[mgr.securityPolicy setValidatesDomainName:NO];
b.不校驗(yàn)證書(shū)
// 初始化單例類(lèi)
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
// 設(shè)置非校驗(yàn)證書(shū)模式
manager.securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
manager.securityPolicy.allowInvalidCertificates = YES;
[manager.securityPolicy setValidatesDomainName:NO];