IOS網絡請求之AFNetWorking 3.x 使用詳情
前言:
計劃把公司的網絡請求與業(yè)務解耦,所以想著學習一下網絡請求,最近學習了NSURLSession,今天來學習一下基于NSURLSession封裝的優(yōu)秀開源框架AFNetWorking 3.x,之前13年做iOS開發(fā)時用的ASIHttpRequest開源框架。
AFNetWorking
AFNetWorking一款輕量級網絡請求開源框架,基于iOS和mac os 網絡進行擴展的高性能框架,大大降低了iOS開發(fā)工程師處理網絡請求的難度,讓iOS開發(fā)變成一件愉快的事情。
1.)AFHTTPSessionManager請求管理者
-(AFHTTPSessionManager *)sharedManager
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//最大請求并發(fā)任務數
manager.operationQueue.maxConcurrentOperationCount = 5;
// 請求格式
// AFHTTPRequestSerializer 二進制格式
// AFJSONRequestSerializer JSON
// AFPropertyListRequestSerializer PList(是一種特殊的XML,解析起來相對容易)
manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 上傳普通格式
// 超時時間
manager.requestSerializer.timeoutInterval = 30.0f;
// 設置請求頭
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
// 設置接收的Content-Type
manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];
// 返回格式
// AFHTTPResponseSerializer 二進制格式
// AFJSONResponseSerializer JSON
// AFXMLParserResponseSerializer XML,只能返回XMLParser,還需要自己通過代理方法解析
// AFXMLDocumentResponseSerializer (Mac OS X)
// AFPropertyListResponseSerializer PList
// AFImageResponseSerializer Image
// AFCompoundResponseSerializer 組合
manager.responseSerializer = [AFJSONResponseSerializer serializer];//返回格式 JSON
//設置返回C的ontent-type
manager.responseSerializer.acceptableContentTypes=[[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];
return manager;
}
2.)處理get請求
-(void)doGetRequest
{
//創(chuàng)建請求地址
NSString *url=@"http://api.nohttp.net/method";
//構造參數
NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};
//AFN管理者調用get請求方法
[[self shareAFNManager] GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
//返回請求返回進度
NSLog(@"downloadProgress-->%@",downloadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請求成功返回數據 根據responseSerializer 返回不同的數據格式
NSLog(@"responseObject-->%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請求失敗
NSLog(@"error-->%@",error);
}];
}
3.)處理post請求
-(void)doPostRequestOfAFN
{
//創(chuàng)建請求地址
NSString *url=@"http://api.nohttp.net/postBody";
//構造參數
NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};
//AFN管理者調用get請求方法
[[self shareAFNManager] POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
//返回請求返回進度
NSLog(@"downloadProgress-->%@",uploadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請求成功返回數據 根據responseSerializer 返回不同的數據格式
NSLog(@"responseObject-->%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請求失敗
NSLog(@"error-->%@",error);
}];
}
4.)處理文件上傳
-(void)doUploadRequest
{
// 創(chuàng)建URL資源地址
NSString *url = @"http://api.nohttp.net/upload";
// 參數
NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};
[[self shareAFNManager] POST:url parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> _Nonnull formData) {
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval a=[dat timeIntervalSince1970];
NSString* fileName = [NSString stringWithFormat:@"file_%0.f.txt", a];
[FileUtils writeDataToFile:fileName data:[@"upload_file_to_server" dataUsingEncoding:NSUTF8StringEncoding]];
// 獲取數據轉換成data
NSString *filePath =[FileUtils getFilePath:fileName];
// 拼接數據到請求題中
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:@"headUrl" fileName:fileName mimeType:@"application/octet-stream" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
// 上傳進度
NSLog(@"%lf",1.0 *uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請求成功
NSLog(@"請求成功:%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請求失敗
NSLog(@"請求失敗:%@",error);
}];
}
5.)處理文件下載
-(void)doDownLoadRequest
{
NSString *urlStr =@"http://images2015.cnblogs.com/blog/950883/201701/950883-20170105104233581-62069155.png";
// 設置請求的URL地址
NSURL *url = [NSURL URLWithString:urlStr];
// 創(chuàng)建請求對象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 下載任務
NSURLSessionDownloadTask *task = [[self shareAFNManager] downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
// 下載進度
NSLog(@"當前下載進度為:%lf", 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
// 下載地址
NSLog(@"默認下載地址%@",targetPath);
//這里模擬一個路徑 真實場景可以根據url計算出一個md5值 作為fileKey
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval a=[dat timeIntervalSince1970];
NSString* fileKey = [NSString stringWithFormat:@"/file_%0.f.txt", a];
// 設置下載路徑,通過沙盒獲取緩存地址,最后返回NSURL對象
NSString *filePath = [FileUtils getFilePath:fileKey];
return [NSURL fileURLWithPath:filePath]; // 返回的是文件存放在本地沙盒的地址
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
// 下載完成調用的方法
NSLog(@"filePath---%@", filePath);
NSData *data=[NSData dataWithContentsOfURL:filePath];
UIImage *image=[UIImage imageWithData:data];
// 刷新界面...
UIImageView *imageView =[[UIImageView alloc]init];
imageView.image=image;
[self.view addSubview:imageView];
[imageView mas_makeConstraints:^(MASConstraintMaker *make) {
make.center.equalTo(self.view);
make.size.mas_equalTo(CGSizeMake(300, 300));
}];
}];
//啟動下載任務
[task resume];
}
6.)網絡狀態(tài)監(jiān)聽
- (void)aFNetworkStatus{
//創(chuàng)建網絡監(jiān)測者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
/*枚舉里面四個狀態(tài) 分別對應 未知 無網絡 數據 WiFi
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1, 未知
AFNetworkReachabilityStatusNotReachable = 0, 無網絡
AFNetworkReachabilityStatusReachableViaWWAN = 1, 蜂窩數據網絡
AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi
};
*/
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
//這里是監(jiān)測到網絡改變的block 可以寫成switch方便
//在里面可以隨便寫事件
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知網絡狀態(tài)");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"無網絡");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"蜂窩數據網");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WiFi網絡");
break;
default:
break;
}
}] ;
[manager startMonitoring];
}
AFNetWorking內存泄露
通常情況我們一般會認為以manager結尾的都是單例模式,所以我們一般都是這樣使用AFNetWorking,如下
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
其實我們點進去查看源碼發(fā)現并不是單例,而是每次都實例化一個AFHTTPSessionManager對象,源碼如下
+ (instancetype)manager {
return [[[self class] alloc] initWithBaseURL:nil];
}
所以我們在使用AFNetWorking的時候要對AFHTTPSessionManager進行單例封裝
+ (AFHTTPSessionManager *)sharedManager
{
static AFHTTPSessionManager *manager = nil;
static dispatch_once_t predicate;
dispatch_once(&predicate, ^{
manager = [AFHTTPSessionManager manager];
manager.operationQueue.maxConcurrentOperationCount = 5;
manager.requestSerializer.timeoutInterval=30.f;
manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
});
return manager;
}
AFNetWorking關于HTTPS
在2017年1月1日起Apple 要求開發(fā)者于年底之前為提交至 App Store 中的應用啟用 HTTPS ,以支持 iOS 9 引入的 ATS(App Transport Security)技術。但后來,apple 發(fā)布聲明宣布延長這個時限,提供給開發(fā)者更多的時間進行相關準備。目前 Apple 尚未公布新的截止日期。所以目前應對https的方案有兩種。
第一種方式:
屏蔽調iOS ATS(App Transport Security),在pList.info文件中添加如下代碼
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
第二種方式:
配置https CA證書,這里采用獲取NSBundle中獲取CA證書,AFNetWorking提供了配置AFSecurityPolicy模塊
+ (AFSecurityPolicy *)customSecurityPolicy{
//Https CA證書地址
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"XueLeTSHTTPS" ofType:@"cer"];
//獲取CA證書數據
NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
//創(chuàng)建AFSecurityPolicy對象
AFSecurityPolicy *security = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
//設置是否允許不信任的證書(證書無效、證書時間過期)通過驗證 ,默認為NO.
security.allowInvalidCertificates = YES;
//是否驗證域名證書的CN(common name)字段。默認值為YES。
security.validatesDomainName = NO;
//根據驗證模式來返回用于驗證服務器的證書
security.pinnedCertificates = [NSSet setWithObject:cerData];
return security;
}
然后通過設置AFHTTPSessionManager的securityPolicy屬性等于自定義的AFSecurityPolicy。
總結:
簡單記錄一下AFNetWorking的基本使用,方便以后查找。
以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支持腳本之家。
相關文章
IOS 出現問題POST網絡請求狀態(tài)code:500的解決方法
這篇文章主要介紹了IOS 出現問題POST網絡請求狀態(tài)code:500的解決方法的相關資料,需要的朋友可以參考下2017-02-02

