基於AFNetWorking搭建APP的網絡請求框架[iOS]

自從AFNetWorking(下文簡稱AFN)更新2.0版本以後,AFN的許多的問題獲得的有效的解決,寫法也獲得了完善。前期主流的第三方網絡類庫 ASI做者宣佈再也不維護,國內大多數的主流APP都逐步接受並開始採用AFN。出於各自公司項目的不一樣須要,你們都會在AFN的基礎上加一層不盡相同的封 裝。不少新APP在選擇方式時也會很是糾結。如何封裝纔可讓AFN更有效率更方便的應用於項目呢,對於這個問題,各人有各人的見解。基於作過以及讀過的 幾個項目,也來談一下如何搭建一個APP的網絡請求框架。因爲本人水平有限,文章不免有不足之處,還請海涵並指正。
本文源地址:http://386502324.blog.163.com/blog/static/113469377201591211312665/
一:瞭解AFN的基本使用
經過AFN類庫在Github的API文檔,咱們能夠大體知道AFN的基本用法。先看其API最基本的請求方式

Get請求:html

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; [manager GET:@"http://example.com/resources.json" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"JSON: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }];

POST表單請求:web

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; [manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileURL:filePath name:@"image" error:nil]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Success: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }];

POST多參數請求:json

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager]; NSDictionary *parameters = @{@"foo": @"bar"}; NSURL *filePath = [NSURL fileURLWithPath:@"file://path/to/image.png"]; [manager POST:@"http://example.com/resources.json" parameters:parameters constructingBodyWithBlock:^(id<AFMultipartFormData> formData) { [formData appendPartWithFileURL:filePath name:@"image" error:nil]; } success:^(AFHTTPRequestOperation *operation, id responseObject) { NSLog(@"Success: %@", responseObject); } failure:^(AFHTTPRequestOperation *operation, NSError *error) { NSLog(@"Error: %@", error); }];

能夠看到官方直接使用AFHTTPRequestOperationManager完成了請求的發起、完成等。AFHTTPRequestOperationManager這個類的做用,官方是這麼說的:

AFHTTPRequestOperationManager encapsulates the common patterns of communicating with a web application over HTTP, including request creation, response serialization, network reachability monitoring, and security, as well as request operation management.

AFHTTPRequestOperationManager封裝了通用的模式去進行網絡請求的建立、網絡請求的響應、網絡狀態的監控、網絡的安全設置、以及網絡請求的管理。【筆者譯】


二:項目中如何使用
AFHTTPRequestOperationManager的完全封裝確實可以很是方便的完成一個網絡請求。可是若是你想對於一個具體網絡請求進行本身的特殊化定製,也就是對一個operation進行特殊處理。通常咱們會建立一個繼承自AFHTTPRequestOperation的子類好比命名爲CQHTTPRequestOperation。
在子類裏,咱們能夠給每個operation增長一個不一樣標識。經過標識,咱們就能夠從隊列中拿到每個具體的網絡請求,也就是某一個operation,對其進行你想要的處理。
固然,這個operation實際上仍是使用
AFHTTPRequestOperationManager進行建立、管理。下方的manager爲其 實例。
數組

operation= (CQNetWorkOperation *)[Manager GET:url parameters:parmar success:^(AFHTTPRequestOperation *operation, id responseObject) {
[weakSelf handleNewResponse:operation error:nil onCompletinBlock:completionBlock];
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
[weakSelf handleNewResponse:operation error:error onCompletinBlock:completionBlock];
}];


安全


三:數據處理
從第二部分的代碼區能夠看到,AFN以返回數據標識爲結束。通常來講,返回的都是data。可是咱們不想在每個網絡請求中分別進行處理,有沒有一種辦法,統一處理返回的數據呢?固然能夠的。在此推薦使用Mantle。
咱們能夠新建一個類,專門用來處理數據的解析;例如,傳入AFN請求後獲得的data,而後統一處理。CQResponseResult爲向外拋出的結果model。處理的第一步,校驗一下data的可用性,根據返回的數據的類型,給model賦值成字典、數組字符串等。若是數據有問題,也能夠給該model的相應屬性賦值。固然最後不要忘掉的是,結果必定要放到主線程拋出。
網絡

+(void)parseOCResponseObject:(id)responseObject modelClass:(Class )modelClass error:(NSError *)error onCompletionBlock:(OCResponseResultBlock)completionBlock{
CQResponseResult *responseResult=[OCResponseResult responseResultWithOCResponseObject:responseObject error:error];
if (responseResult.responseData != nil && responseResult.responseData != [NSNull null]&&modelClass ){
if ([responseResult.responseData isKindOfClass:[NSDictionary class]]) {
NSError *aError;
MTLModel *dataModel=[MTLJSONAdapter modelOfClass:modelClass fromJSONDictionary:responseResult.responseData error:&aError];
if (dataModel&&nil==aError) {
responseResult.responseData=dataModel;
}
}else if ([responseResult.responseData isKindOfClass:[NSArray class]]){
responseResult.responseData = [MTLJSONAdapter modelsOfClass:modelClass fromJSONArray:responseResult.responseData error:nil];
}else if ([responseResult.responseData isKindOfClass:[NSString class]]){
//若是是字符串,暫時不作處理

}
}
dispatch_async(dispatch_get_main_queue(), ^{
completionBlock(responseResult);
});
}


app

四:綜述
設計一:
1:建立CQHttpClient類,繼承自基類。用來處理manager和operation。
框架

- (void )get:(NSString *)URLString parameters:(NSDictionary *)parameters
resultBack:(NetworkBackBlock)resultBack
{
NSMutableSet *contentTypes = [[NSMutableSet alloc] initWithSet:operationManager.responseSerializer.acceptableContentTypes];
if (contentTypes) {
[contentTypes addObject:@"text/html"];
[contentTypes addObject:@"application/json"];
}
operationManager.responseSerializer.acceptableContentTypes = contentTypes;
[operationManager GET:URLString parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
CommonResult *result = [NWCommonResult resultWithData:MC_RESULT_CODE_SUCCESS resultDesc:nil];
DDLogInfo(@"operation::%@::::%@",parameters,operation.responseString);
resultBack(result, RESULT_OBJECT(operation));
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
DDLogInfo(@"error::%@::::%@:::%@",parameters,operation.responseString,error);
CommonResult *result = [NWCommonResult resultWithData:MC_RESULT_CODE_FAILURE resultDesc:[error description]];
resultBack(result, nil);
}];
}
async


2:若是operation不須要單獨處理,能夠再建立一個類CQNetWork.h,集成自基類。這個類,就是外界請求,使用的類。一些網絡相關的方法例如獲取網絡狀態能夠放到這裏面完成。另外,最重要的是,咱們能夠在這個類裏面,使用上面
CQHttpClient的寫出公共的方法,不須要外界關注operation的概念,直接完成一個請求

post

- (void)post:(NSString *)urlString parameters:(NSMutableDictionary *)parameters isCache:(BOOL) isCache cacheTime:(NSTimeInterval)timeInterval resultBack:(NetworkBackBlock)resultBack
{

if (MC_NETWORK_STATUS_NONE == [self getNetworkStatus]) {
NWCommonResult *result = [NWCommonResult resultWithData:MC_RESULT_CODE_NETWORK_FAILURE resultDesc:nil];
resultBack(result, nil);
return;
}

CQHttpClient *httpClient = [self baseHttpRequest];
if (_config &&[_config respondsToSelector:@selector(getToken:)]) {
// [parameters setObject:[_config getToken:urlString] forKey:@"token"];
[httpClient addValue:[_config getToken:urlString] forHTTPHeaderField:@"Cookie"];
}
if (_config &&[_config respondsToSelector:@selector(getRequestUDID)]) {
httpClient.UDIDDate = [_config getRequestUDID];
NSLog(@"httpClient.UDIDDatehttpClient.UDIDDate:::%@",httpClient.UDIDDate);
}

/**
* 主要生成文件的名字
*/
_urlString = urlString;
_parameters = parameters;
_isCache = isCache;
_timeInteval = timeInterval;

if ([self compareSecondsLoadCache]) {
CommonResult *result = [NWCommonResult resultWithData:MC_RESULT_CODE_SUCCESS resultDesc:nil];
resultBack(result, [self cacheJson]);
return;
}


[httpClient post:urlString parameters:parameters resultBack:^(NWCommonResult *result, id responseObject) {
result.UDIDDate = httpClient.UDIDDate;
resultBack(result,responseObject);
}];
}

3:數據處理

+(CQResponseResult *)responseResultWithOCResponseObject:(id)responseObject error:(NSError *)aError{
CQResponseResult *responeResult=[[OCResponseResult alloc] init];
if (responseObject != nil && responseObject != [NSNull null]&&nil==aError ) {
if ([responseObject isKindOfClass:[NSDictionary class]]){
[CQResponseResult parseOCResponesDic:responseObject withResponseResut:&responeResult];
}else if([responseObject isKindOfClass:[NSData class]]){
NSError *jsonError;
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:responseObject options:NSJSONReadingMutableLeaves error:&jsonError];
if (dic&&nil==jsonError) {
[OCResponseResult parseOCResponesDic:dic withResponseResut:&responeResult];
}else{
responeResult.responseCode=OCCodeStateFailed;
responeResult.responseMessage=OCNetWorkErrorMessage;
}
}else if ([responseObject isKindOfClass:[NSString class]]){
NSData *aData=[responseObject dataUsingEncoding:4];
NSError *jsonError;
NSDictionary *dic=[NSJSONSerialization JSONObjectWithData:aData options:NSJSONReadingMutableLeaves error:&jsonError];
if (dic&&nil==jsonError) { [OCResponseResult parseOCResponesDic:dic withResponseResut:&responeResult]; }else{ responeResult.responseCode=OCCodeStateFailed; responeResult.responseMessage=OCNetWorkErrorMessage; } }else{ responeResult.responseCode=OCCodeStateFailed; responeResult.responseMessage=OCNetWorkErrorMessage; } }else{ responeResult.responseCode=OCCodeStateFailed; responeResult.responseMessage=OCNetWorkErrorMessage; } return responeResult;}


設計二:

第二步中,外界仍是須要關注opreation的概念的。將其拋給外界便可。

相關文章
相關標籤/搜索