AFNetworking封裝-項目使用

本篇博客是接着上一篇AFNetworking源碼解析的後續,若是想對AFNetworking源碼有所瞭解。javascript

請讀一下http://www.javashuo.com/article/p-qphuutmo-bt.htmlhtml

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源碼解析。

相關文章
相關標籤/搜索