本篇博客是接着上一篇AFNetworking源碼解析的後續,若是想對AFNetworking源碼有所瞭解。javascript
請讀一下http://www.javashuo.com/article/p-qphuutmo-bt.html。html
YTKNetwork的源碼詳解:http://www.javashuo.com/article/p-spkgoewu-bv.htmljava
這篇博客主要是對AFNetworking代碼進行封裝,也是本身在實際項目中所使用過的(對中小型企業或者項目)可直接使用,也會在github上傳(偷偷竊喜一下,一直想在github上有所項目,一直沒有時間),趁着端午幾天有時間,給github貢獻點本身力量。本篇讀下來大約10-15分鐘,歡迎指正。ios
一.結構解析git
最核心(可直接拖拽到新項目中)github
(拓展cocoapods的拖入) 拖入以前,須要導入AFNetworking,最好利用cocoapods導入,cocoapods導入時json
vim Podfile --->輸入i
platform :ios, '8.0' target "targetName" do pod 'AFNetworking' end
(有一點在而後按Esc,而且輸入「 :」號進入vim命令模式,而後在冒號後邊輸入wq)最後pod install。編譯一下,拖入項目的類就行了,就不會編譯錯誤。vim
二.分類講解網絡
1.Singletonapp
#import <UIKit/UIKit.h> //////////////////////////////////////////////////////////////////////////////// // 申明和定義單例對象: // AS_SINGLETON( XxxClass ); // DEF_SINGLETON( XxxClass ); #undef AS_SINGLETON #define AS_SINGLETON( __class ) \ - (__class *)sharedInstance; \ + (__class *)sharedInstance; #undef DEF_SINGLETON #define DEF_SINGLETON( __class ) \ - (__class *)sharedInstance \ { \ return [__class sharedInstance]; \ } \ + (__class *)sharedInstance \ { \ static dispatch_once_t once; \ static __class * __singleton__; \ dispatch_once( &once, ^{ __singleton__ = [[[self class] alloc] init]; } ); \ return __singleton__; \ }
經過Singleton,來聲明和定義單例對象。
聲明單例
// 聲明單例 AS_SINGLETON(APIClient);
定義單例
// 定義單例 DEF_SINGLETON(APIClient);
2.APIClient.h
(1)請求響應的狀態
// 請求響應的狀態 typedef NS_ENUM(NSInteger, ApiRequestStatusCode) { ApiRequestNotReachable = -2, // 當前網絡已斷開 ApiRequestErr = -1, // 請求出錯 ApiRequestOK = 0, // 請求成功 };
當時的請求響應狀態只有三個,故定義一個枚舉表示請求響應的狀態。
(2)請求的方法類型
// 請求的方法類型 typedef NS_ENUM(NSInteger, HttpMethod) { GET = 0, POST = 1, DELETE = 2, PUT = 3, PATH_GET = 4, // GET請求,填充參數到url上,處理@"user/account/check/{phone}",{phone}這種狀況 QUERY_GET = 5, // GET請求,填充query參數到url上,處理"?a=1&b=2"這種狀況 };
(3)請求相應的block
// 請求響應Block typedef void (^APIClientRequestResponse)(ApiRequestStatusCode requestStatusCode, id JSON);
(4)經過設置代理攔截成功響應數據
@protocol APIClientDelegate <NSObject> @required // 攔截成功請求響應數據進行處理 - (void)handleSuccessRequest:(id)JSON completion:(void(^)(id aJSON))cb; @end
在.h中還有一些方法屬性
// 爲處理攔截的響應數據而設置的委託 @property (nonatomic, weak) id<APIClientDelegate> delegate; // 聲明單例 AS_SINGLETON(APIClient); // 獲取當前的網絡狀態類型(返回:0-No wifi or cellular(無網絡), 1-2G, 2-3G, 3-4G, 4-LTE, 5-wifi) + (int)networkType; // 網絡狀態監聽,應用當前是否有網絡:有返回YES,沒有返回NO + (void)networkReachableWithBlock:(void(^)(BOOL isReachable))block; // 發送請求,返回JSON格式的響應數據 + (void)requestURL:(NSString *)urlString httpMethod:(HttpMethod)method params:(NSDictionary *)params response:(APIClientRequestResponse)response; // 取消掉全部網絡請求 + (void)cancelAllRequest;
3.APIClient.m
(1)建立請求管理對象
@property (nonatomic, strong) AFHTTPSessionManager *manager;
(2)獲取當前的網絡狀態類型
// 獲取當前的網絡狀態類型(返回:0-No wifi or cellular(無網絡), 1-2G, 2-3G, 3-4G, 4-LTE, 5-wifi) + (int)networkType { NSArray *subviews = [[[[UIApplication sharedApplication] valueForKey:@"statusBar"] valueForKey:@"foregroundView"]subviews]; NSNumber *dataNetworkItemView = nil; for (id subview in subviews) { if([subview isKindOfClass:[NSClassFromString(@"UIStatusBarDataNetworkItemView") class]]) { dataNetworkItemView = subview; break; } } int ret = 0; switch ([[dataNetworkItemView valueForKey:@"dataNetworkType"] integerValue]) { case 0: ret = 0; break; case 1: ret = 1; break; case 2: ret = 2; break; case 3: ret = 3; break; case 4: ret = 4; break; case 5: ret = 5; break; default: break; } return ret; }
(3)網絡狀態監聽,應用當前是否有網絡
// 網絡狀態監聽,應用當前是否有網絡 + (void)networkReachableWithBlock:(void(^)(BOOL isReachable))block { [[AFNetworkReachabilityManager sharedManager] startMonitoring]; [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) { switch (status) { case AFNetworkReachabilityStatusReachableViaWWAN: case AFNetworkReachabilityStatusReachableViaWiFi: { if (block) { block(YES); } break; } case AFNetworkReachabilityStatusNotReachable: { if (block) { block(NO); } break; } default: break; } }]; //結束監聽 //[[AFNetworkReachabilityManager sharedManager] stopMonitoring]; }
(3)請求最重要最核心的代碼
// 發送請求,返回JSON格式的響應數據 + (void)requestURL:(NSString *)urlString httpMethod:(HttpMethod)method params:(NSDictionary *)params response:(APIClientRequestResponse)response { if ([APIClient networkType] > 0) { APIClient *client = [APIClient sharedInstance]; if (!client.manager) { AFHTTPSessionManager *manager = [AFHTTPSessionManager manager]; manager.requestSerializer.timeoutInterval = 30; manager.requestSerializer = [AFHTTPRequestSerializer serializer]; manager.responseSerializer = [AFJSONResponseSerializer serializer]; AFJSONResponseSerializer *responseSerializer = [AFJSONResponseSerializer serializerWithReadingOptions:NSJSONReadingAllowFragments]; manager.responseSerializer = responseSerializer; manager.responseSerializer.acceptableContentTypes = [NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript",@"text/html",@"text/plain",@"application/x-www-form-urlencodem", nil]; client.manager = manager; } __weak typeof(self)weakSelf = self; switch (method) { case PATH_GET: { urlString = [APIClient pathGet:urlString params:params]; // //LOG(@"PATH_GET http_url:%@",urlString); [client.manager GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { if (response) { response(ApiRequestErr, nil); } }]; break; } case QUERY_GET: { urlString = [APIClient queryGet:urlString params:params]; //LOG(@"QUERY_GET http_url:%@",urlString); [client.manager GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { if (response) { response(ApiRequestErr, nil); } }]; break; } case GET: { // //LOG(@"GET http_url:%@",urlString); [client.manager GET:urlString parameters:nil progress:nil success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { if (response) { response(ApiRequestErr, nil); //LOG(@"GET http_url:%@",urlString); } }]; break; } case POST: { // //LOG(@"POST http_url:%@",urlString); [client.manager POST:urlString parameters:params progress:nil success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { // //LOG(@"%@",error); if (response) { response(ApiRequestErr, nil); } }]; break; } case DELETE: { //LOG(@"DELETE http_url:%@",urlString); [client.manager DELETE:urlString parameters:nil success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { if (response) { response(ApiRequestErr, nil); } }]; break; } case PUT: { //LOG(@"PUT http_url:%@",urlString); [client.manager PUT:urlString parameters:params success:^(NSURLSessionDataTask * __unused task, id JSON) { __strong typeof(weakSelf)strongSelf = weakSelf; if (strongSelf) { [strongSelf handleSuccessRequest:JSON cb:response]; } } failure:^(NSURLSessionDataTask *__unused task, NSError *error) { if (response) { response(ApiRequestErr, nil); } }]; break; } } } else { // 沒有鏈接網絡 if (response) response(ApiRequestNotReachable, nil); } }
(4)統一處理響應數據
// 統一處理響應數據 + (void)handleSuccessRequest:(id)JSON cb:(void(^)(ApiRequestStatusCode requestStatusCode, id JSON))cb { APIClient *client = [APIClient sharedInstance]; if (client.delegate && [client.delegate respondsToSelector:@selector(handleSuccessRequest:completion:)]) { [client.delegate handleSuccessRequest:JSON completion:^(id aJSON) { if (cb) { cb(ApiRequestOK, aJSON); } }]; } else { if (cb) { cb(ApiRequestOK, JSON); } } }
(5)參數拼接
// 填充參數到url上,處理@"user/account/check/{phone}",{phone}這種狀況 + (NSString *)pathGet:(NSString *)uri params:(NSDictionary *)params { if (nil == uri|| nil == params || params.count <= 0) { return uri; } for (NSString *key in params) { NSString *key2 = [NSString stringWithFormat:@"{%@}",key]; if ([uri rangeOfString:key2].location != NSNotFound) { uri = [uri stringByReplacingOccurrencesOfString:key2 withString:params[key]]; } } return [uri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]; } // 填充query參數到url上,處理"?a=1&b=2"這種狀況 + (NSString *)queryGet:(NSString *)uri params:(NSDictionary *)params { if (nil == uri || nil == params || params.count <= 0) { return uri; } NSMutableString *tmpUri = [NSMutableString stringWithString:uri]; int i = 0; for (NSString *key in params) { if (i == 0) { [tmpUri appendFormat:@"?%@=%@",key, params[key]]; } else { [tmpUri appendFormat:@"&%@=%@",key, params[key]]; } i++; } return [tmpUri stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];; }
(6)取消全部網絡請求
// 取消掉全部網絡請求 + (void)cancelAllRequest { APIClient *client = [APIClient sharedInstance]; if (client.manager) { if (client.manager.operationQueue) { [client.manager.operationQueue cancelAllOperations]; } } }
上面就是代碼的主要封裝,能夠應對中小型企業和App的要求。
三.使用
1.新建API.h繼承NSObject
2.在API.m使用
3.在控制器裏面調用以下
WS(weakSelf); if ([APIClient networkType] > 0){ //獲取我的界面的信息 [API1 getEvaluateMeDataWithCB:^(ApiRequestStatusCode requestStatusCode, id JSON) { switch (requestStatusCode) { case ApiRequestOK: { //正確解析json,以及UI處理break; } } case ApiRequestErr: [MBProgressHUD showError:kErrTip]; break; case ApiRequestNotReachable: [MBProgressHUD showError:kNotReachableTip]; break; default: break; } }]; }else{ [MBProgressHUD showError:kNotReachableTip]; }
上面就是針對AFNetworking的簡單封裝,能夠知足網絡請求的封裝。
本次代碼的demo已上傳git。github地址:https://github.com/zxy1829760/testAF
歡迎指正!!!
下一篇講述另外一篇關於網絡封裝的YTKNetwork源碼解析。