以前都是直接複製粘貼二次封裝好的代碼 , 現在都忘了怎麼寫 . 恰好當前項目要用到請求頭 , 在網上學習了一下 , 統一敲了一遍 .自從到了現在公司 , 才發現要學的東西太多了 , 當然 , 有個好的老大比什麼都重要… 能學到不少的東西…
創建兩個類 , 一個類用於封裝AFN , 一個類用作返回值模型
response模型類
#import <Foundation/Foundation.h>
@interface netWorkResponse : NSObject
//實際遠不止這些屬性
@property (assign, nonatomic) BOOL isSuccess;
@property (strong, nonatomic) NSError *error;
@property (strong, nonatomic) id data;
@property (assign, nonatomic) NSInteger statusCode;
//單例
+ (instancetype)shareInstance;
@end
#import "netWorkResponse.h"
static netWorkResponse *responseModel = nil;
#pragma mark - 模型類
/**
模型類
*/
@implementation netWorkResponse
+ (instancetype)shareInstance
{
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
responseModel = [[netWorkResponse alloc]init];
});
return responseModel;
}
@end
封裝網絡請求類
#import "NetWorkTool.h"
#import "AFNetworking.h"
#pragma mark - 網絡請求manager
/**
繼承AFHTTPSessionManager 單例
*/
@interface AFHttpManager : AFHTTPSessionManager
@end
manager參數配置
繼承AFN原生httpmanager , 用於生成單例 , 配置請求的一些參數 , 比如 基地址 , 請求頭 , 接收返回類型等
@implementation AFHttpManager
//設置單例
+ (AFHttpManager *)sharedManager
{
static AFHttpManager *httpManager = nil;
static dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//如果設置了 服務器主地址 , 那麼後面請求就不用拼接了 .
//當然我試了下這裏加主地址 , 請求時又拼接了主地址 , 也訪問成功了.
// AFHttpManager *httpManager = [AFHTTPSessionManager alloc]initWithBaseURL:<#(nullable NSURL *)#>
httpManager = [AFHttpManager manager];
// httpManager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json",@"text/html", @"text/json", @"text/javascript",@"text/plain",@"image/gif", nil];
//現在貌似不用寫接收類型了,試了試訪問@"https://baidu.com",提示不能接收@"text/html"類型 , 我寫下述一句 , 和寫上面接收類型一樣的效果
httpManager.responseSerializer = [AFHTTPResponseSerializer serializer];
//設置訪問請求頭 , 請求頭是服務器限制用來限制訪問而要求客戶端添加的一個標識 . 就好比是一個暗號 . 如果服務端沒做要求 , 不用加請求頭也可以
[httpManager.requestSerializer setValue:@"doAction" forHTTPHeaderField:@"te_method"];
[httpManager.requestSerializer setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
[httpManager.requestSerializer setValue:@"2.2" forHTTPHeaderField:@"te_version"];
[httpManager.requestSerializer setValue:@"moa" forHTTPHeaderField:@"party_id"];
});
//設置安全策略 (https) ,數字證書驗證,此段具體實現 , 後期更新 ...
httpManager.securityPolicy = [httpManager customSecurityPolicy];
return httpManager;
}
下述證書驗證方法轉自cocoachina
http://www.cocoachina.com/bbs/read.php?tid-325551-page-2.html
- (AFSecurityPolicy*)customSecurityPolicy
{
// /先導入證書
NSString *cerPath = [[NSBundle mainBundle] pathForResource:@"**.cer" ofType:@""];//證書的路徑
NSData *certData = [NSData dataWithContentsOfFile:cerPath];
// AFSSLPinningModeCertificate 使用證書驗證模式
AFSecurityPolicy *securityPolicy = [AFSecurityPolicy policyWithPinningMode:AFSSLPinningModeCertificate];
// allowInvalidCertificates 是否允許無效證書(也就是自建的證書),默認爲NO
// 如果是需要驗證自建證書,需要設置爲YES
securityPolicy.allowInvalidCertificates = YES;
//validatesDomainName 是否需要驗證域名,默認爲YES;
//假如證書的域名與你請求的域名不一致,需把該項設置爲NO;如設成NO的話,即服務器使用其他可信任機構頒發的證書,也可以建立連接,這個非常危險,建議打開。
//置爲NO,主要用於這種情況:客戶端請求的是子域名,而證書上的是另外一個域名。因爲SSL證書上的域名是獨立的,假如證書上註冊的域名是www.google.com,那麼mail.google.com是無法驗證通過的;當然,有錢可以註冊通配符的域名*.google.com,但這個還是比較貴的。
//如置爲NO,建議自己添加對應域名的校驗邏輯。
securityPolicy.validatesDomainName = NO;
securityPolicy.pinnedCertificates = [NSSet setWithObject:certData];
return securityPolicy;
}
@end
封裝工具類實現
當訪問服務器成功或失敗後 , 將信息賦值給模型 , 統一傳回 ,這樣比較整潔一些 , 不會很凌亂
/**
封裝的網絡工具類
*/
@implementation NetWorkTool
//此處就僅以一個get請求爲例 , post請求大同小異
+ (void)getRequestWithUrl:(NSString *)urlString parameters:(id)parameters response:(response)callback
{
//響應對象
netWorkResponse *response = [netWorkResponse shareInstance];
[[AFHttpManager sharedManager]GET:urlString parameters:parameters progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
response.isSuccess = YES;
//將responseObject 數據賦值給 response , 操作省略
callback(response);
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
response.isSuccess = NO;
response.error = error; //此處錯誤可根據服務器返回狀態 , 自行返回具體的錯誤
callback(response);
}];
}