IOS網(wǎng)絡(luò)請(qǐng)求之AFNetWorking 3.x 使用詳情
前言:
計(jì)劃把公司的網(wǎng)絡(luò)請(qǐng)求與業(yè)務(wù)解耦,所以想著學(xué)習(xí)一下網(wǎng)絡(luò)請(qǐng)求,最近學(xué)習(xí)了NSURLSession,今天來(lái)學(xué)習(xí)一下基于NSURLSession封裝的優(yōu)秀開(kāi)源框架AFNetWorking 3.x,之前13年做iOS開(kāi)發(fā)時(shí)用的ASIHttpRequest開(kāi)源框架。
AFNetWorking
AFNetWorking一款輕量級(jí)網(wǎng)絡(luò)請(qǐng)求開(kāi)源框架,基于iOS和mac os 網(wǎng)絡(luò)進(jìn)行擴(kuò)展的高性能框架,大大降低了iOS開(kāi)發(fā)工程師處理網(wǎng)絡(luò)請(qǐng)求的難度,讓iOS開(kāi)發(fā)變成一件愉快的事情。
1.)AFHTTPSessionManager請(qǐng)求管理者
-(AFHTTPSessionManager *)sharedManager
{
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
//最大請(qǐng)求并發(fā)任務(wù)數(shù)
manager.operationQueue.maxConcurrentOperationCount = 5;
// 請(qǐng)求格式
// AFHTTPRequestSerializer 二進(jìn)制格式
// AFJSONRequestSerializer JSON
// AFPropertyListRequestSerializer PList(是一種特殊的XML,解析起來(lái)相對(duì)容易)
manager.requestSerializer = [AFHTTPRequestSerializer serializer]; // 上傳普通格式
// 超時(shí)時(shí)間
manager.requestSerializer.timeoutInterval = 30.0f;
// 設(shè)置請(qǐng)求頭
[manager.requestSerializer setValue:@"gzip" forHTTPHeaderField:@"Content-Encoding"];
// 設(shè)置接收的Content-Type
manager.responseSerializer.acceptableContentTypes = [[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];
// 返回格式
// AFHTTPResponseSerializer 二進(jìn)制格式
// AFJSONResponseSerializer JSON
// AFXMLParserResponseSerializer XML,只能返回XMLParser,還需要自己通過(guò)代理方法解析
// AFXMLDocumentResponseSerializer (Mac OS X)
// AFPropertyListResponseSerializer PList
// AFImageResponseSerializer Image
// AFCompoundResponseSerializer 組合
manager.responseSerializer = [AFJSONResponseSerializer serializer];//返回格式 JSON
//設(shè)置返回C的ontent-type
manager.responseSerializer.acceptableContentTypes=[[NSSet alloc] initWithObjects:@"application/xml", @"text/xml",@"text/html", @"application/json",@"text/plain",nil];
return manager;
}
2.)處理get請(qǐng)求
-(void)doGetRequest
{
//創(chuàng)建請(qǐng)求地址
NSString *url=@"http://api.nohttp.net/method";
//構(gòu)造參數(shù)
NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};
//AFN管理者調(diào)用get請(qǐng)求方法
[[self shareAFNManager] GET:url parameters:parameters progress:^(NSProgress * _Nonnull downloadProgress) {
//返回請(qǐng)求返回進(jìn)度
NSLog(@"downloadProgress-->%@",downloadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請(qǐng)求成功返回?cái)?shù)據(jù) 根據(jù)responseSerializer 返回不同的數(shù)據(jù)格式
NSLog(@"responseObject-->%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請(qǐng)求失敗
NSLog(@"error-->%@",error);
}];
}
3.)處理post請(qǐng)求
-(void)doPostRequestOfAFN
{
//創(chuàng)建請(qǐng)求地址
NSString *url=@"http://api.nohttp.net/postBody";
//構(gòu)造參數(shù)
NSDictionary *parameters=@{@"name":@"yanzhenjie",@"pwd":@"123"};
//AFN管理者調(diào)用get請(qǐng)求方法
[[self shareAFNManager] POST:url parameters:parameters progress:^(NSProgress * _Nonnull uploadProgress) {
//返回請(qǐng)求返回進(jìn)度
NSLog(@"downloadProgress-->%@",uploadProgress);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請(qǐng)求成功返回?cái)?shù)據(jù) 根據(jù)responseSerializer 返回不同的數(shù)據(jù)格式
NSLog(@"responseObject-->%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請(qǐng)求失敗
NSLog(@"error-->%@",error);
}];
}
4.)處理文件上傳
-(void)doUploadRequest
{
// 創(chuàng)建URL資源地址
NSString *url = @"http://api.nohttp.net/upload";
// 參數(shù)
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]];
// 獲取數(shù)據(jù)轉(zhuǎn)換成data
NSString *filePath =[FileUtils getFilePath:fileName];
// 拼接數(shù)據(jù)到請(qǐng)求題中
[formData appendPartWithFileURL:[NSURL fileURLWithPath:filePath] name:@"headUrl" fileName:fileName mimeType:@"application/octet-stream" error:nil];
} progress:^(NSProgress * _Nonnull uploadProgress) {
// 上傳進(jìn)度
NSLog(@"%lf",1.0 *uploadProgress.completedUnitCount / uploadProgress.totalUnitCount);
} success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
//請(qǐng)求成功
NSLog(@"請(qǐng)求成功:%@",responseObject);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
//請(qǐng)求失敗
NSLog(@"請(qǐng)求失?。?@",error);
}];
}
5.)處理文件下載
-(void)doDownLoadRequest
{
NSString *urlStr =@"http://images2015.cnblogs.com/blog/950883/201701/950883-20170105104233581-62069155.png";
// 設(shè)置請(qǐng)求的URL地址
NSURL *url = [NSURL URLWithString:urlStr];
// 創(chuàng)建請(qǐng)求對(duì)象
NSURLRequest *request = [NSURLRequest requestWithURL:url];
// 下載任務(wù)
NSURLSessionDownloadTask *task = [[self shareAFNManager] downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
// 下載進(jìn)度
NSLog(@"當(dāng)前下載進(jìn)度為:%lf", 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
} destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
// 下載地址
NSLog(@"默認(rèn)下載地址%@",targetPath);
//這里模擬一個(gè)路徑 真實(shí)場(chǎng)景可以根據(jù)url計(jì)算出一個(gè)md5值 作為fileKey
NSDate* dat = [NSDate dateWithTimeIntervalSinceNow:0];
NSTimeInterval a=[dat timeIntervalSince1970];
NSString* fileKey = [NSString stringWithFormat:@"/file_%0.f.txt", a];
// 設(shè)置下載路徑,通過(guò)沙盒獲取緩存地址,最后返回NSURL對(duì)象
NSString *filePath = [FileUtils getFilePath:fileKey];
return [NSURL fileURLWithPath:filePath]; // 返回的是文件存放在本地沙盒的地址
} completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
// 下載完成調(diào)用的方法
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));
}];
}];
//啟動(dòng)下載任務(wù)
[task resume];
}
6.)網(wǎng)絡(luò)狀態(tài)監(jiān)聽(tīng)
- (void)aFNetworkStatus{
//創(chuàng)建網(wǎng)絡(luò)監(jiān)測(cè)者
AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
/*枚舉里面四個(gè)狀態(tài) 分別對(duì)應(yīng) 未知 無(wú)網(wǎng)絡(luò) 數(shù)據(jù) WiFi
typedef NS_ENUM(NSInteger, AFNetworkReachabilityStatus) {
AFNetworkReachabilityStatusUnknown = -1, 未知
AFNetworkReachabilityStatusNotReachable = 0, 無(wú)網(wǎng)絡(luò)
AFNetworkReachabilityStatusReachableViaWWAN = 1, 蜂窩數(shù)據(jù)網(wǎng)絡(luò)
AFNetworkReachabilityStatusReachableViaWiFi = 2, WiFi
};
*/
[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
//這里是監(jiān)測(cè)到網(wǎng)絡(luò)改變的block 可以寫(xiě)成switch方便
//在里面可以隨便寫(xiě)事件
switch (status) {
case AFNetworkReachabilityStatusUnknown:
NSLog(@"未知網(wǎng)絡(luò)狀態(tài)");
break;
case AFNetworkReachabilityStatusNotReachable:
NSLog(@"無(wú)網(wǎng)絡(luò)");
break;
case AFNetworkReachabilityStatusReachableViaWWAN:
NSLog(@"蜂窩數(shù)據(jù)網(wǎng)");
break;
case AFNetworkReachabilityStatusReachableViaWiFi:
NSLog(@"WiFi網(wǎng)絡(luò)");
break;
default:
break;
}
}] ;
[manager startMonitoring];
}
AFNetWorking內(nèi)存泄露
通常情況我們一般會(huì)認(rèn)為以manager結(jié)尾的都是單例模式,所以我們一般都是這樣使用AFNetWorking,如下
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
其實(shí)我們點(diǎn)進(jìn)去查看源碼發(fā)現(xiàn)并不是單例,而是每次都實(shí)例化一個(gè)AFHTTPSessionManager對(duì)象,源碼如下
+ (instancetype)manager {
return [[[self class] alloc] initWithBaseURL:nil];
}
所以我們?cè)谑褂肁FNetWorking的時(shí)候要對(duì)AFHTTPSessionManager進(jìn)行單例封裝
+ (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關(guān)于HTTPS
在2017年1月1日起Apple 要求開(kāi)發(fā)者于年底之前為提交至 App Store 中的應(yīng)用啟用 HTTPS ,以支持 iOS 9 引入的 ATS(App Transport Security)技術(shù)。但后來(lái),apple 發(fā)布聲明宣布延長(zhǎng)這個(gè)時(shí)限,提供給開(kāi)發(fā)者更多的時(shí)間進(jìn)行相關(guān)準(zhǔn)備。目前 Apple 尚未公布新的截止日期。所以目前應(yīng)對(duì)https的方案有兩種。
第一種方式:
屏蔽調(diào)iOS ATS(App Transport Security),在pList.info文件中添加如下代碼
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
第二種方式:
配置https CA證書(shū),這里采用獲取NSBundle中獲取CA證書(shū),AFNetWorking提供了配置AFSecurityPolicy模塊
+ (AFSecurityPolicy *)customSecurityPolicy{
//Https CA證書(shū)地址
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"XueLeTSHTTPS" ofType:@"cer"];
//獲取CA證書(shū)數(shù)據(jù)
NSData *cerData = [NSData dataWithContentsOfFile:cerPath];
//創(chuàng)建AFSecurityPolicy對(duì)象
AFSecurityPolicy *security = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeNone];
//設(shè)置是否允許不信任的證書(shū)(證書(shū)無(wú)效、證書(shū)時(shí)間過(guò)期)通過(guò)驗(yàn)證 ,默認(rèn)為NO.
security.allowInvalidCertificates = YES;
//是否驗(yàn)證域名證書(shū)的CN(common name)字段。默認(rèn)值為YES。
security.validatesDomainName = NO;
//根據(jù)驗(yàn)證模式來(lái)返回用于驗(yàn)證服務(wù)器的證書(shū)
security.pinnedCertificates = [NSSet setWithObject:cerData];
return security;
}
然后通過(guò)設(shè)置AFHTTPSessionManager的securityPolicy屬性等于自定義的AFSecurityPolicy。
總結(jié):
簡(jiǎn)單記錄一下AFNetWorking的基本使用,方便以后查找。
以上就是本文的全部?jī)?nèi)容,希望對(duì)大家的學(xué)習(xí)有所幫助,也希望大家多多支持腳本之家。
相關(guān)文章
iOS 報(bào)clang: error: no input files錯(cuò)誤的解決方法
這篇文章主要給大家介紹了關(guān)于iOS報(bào)clang: error: no input files錯(cuò)誤的解決方法,文中通過(guò)圖文介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價(jià)值,需要的朋友們下面隨著小編來(lái)一起學(xué)習(xí)學(xué)習(xí)吧。2018-01-01
iOS 防止按鈕多次點(diǎn)擊造成多次響應(yīng)的方法
這篇文章主要介紹了iOS 防止按鈕多次點(diǎn)擊造成多次響應(yīng)的方法的相關(guān)資料,這里對(duì)多次點(diǎn)擊造成的響應(yīng)提供了解決辦法,需要的朋友可以參考下2016-11-11
IOS中的target action控件的實(shí)現(xiàn)
這篇文章主要介紹了IOS中的target action控件的實(shí)現(xiàn)的相關(guān)資料,這里提供實(shí)現(xiàn)target action的簡(jiǎn)單實(shí)例幫助大家學(xué)習(xí)理解該如何實(shí)現(xiàn),需要的朋友可以參考下2017-08-08
詳解iOS App開(kāi)發(fā)中Cookie的管理方法
iOS中主要靠NSHTTPCookieStorage和NSHTTPCookie來(lái)管理Cookie,下面我們就來(lái)詳解iOS App開(kāi)發(fā)中Cookie的管理方法,在最后一部分會(huì)單獨(dú)整理出如何清除Cookie的方法.2016-07-07
iOS block循環(huán)引用詳解及常見(jiàn)誤區(qū)
這篇文章主要介紹了iOS block循環(huán)引用詳解和應(yīng)用,常見(jiàn)誤區(qū)詳解,本文通過(guò)實(shí)例代碼給大家介紹的非常詳細(xì),需要的朋友可以參考下2021-08-08
使用AVFoundation實(shí)現(xiàn)視頻錄制詳解
這篇文章主要介紹了使用AVFoundation實(shí)現(xiàn)視頻錄制詳解的相關(guān)資料,需要的朋友可以參考下2022-09-09
iOS判斷運(yùn)營(yíng)商類型的實(shí)現(xiàn)方法
下面小編就為大家?guī)?lái)一篇iOS判斷運(yùn)營(yíng)商類型的實(shí)現(xiàn)方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-04-04
iOS使用pageViewController實(shí)現(xiàn)多視圖滑動(dòng)切換
這篇文章主要為大家詳細(xì)介紹了iOS使用pageViewController實(shí)現(xiàn)多視圖滑動(dòng)切換,文中示例代碼介紹的非常詳細(xì),具有一定的參考價(jià)值,感興趣的小伙伴們可以參考一下2018-06-06

