AFNetworking封装-项目使用

烂漫一生 提交于 2020-04-24 17:47:26

本篇博客是接着上一篇AFNetworking源码解析的后续,如果想对AFNetworking源码有所了解。

请读一下https://www.cnblogs.com/guohai-stronger/p/9191497.html

YTKNetwork的源码详解:https://www.cnblogs.com/guohai-stronger/p/9194519.html

这篇博客主要是对AFNetworking代码进行封装,也是自己在实际项目中所使用过的(对中小型企业或者项目)可直接使用,也会在github上传(偷偷窃喜一下,一直想在github上有所项目,一直没有时间),趁着端午几天有时间,给github贡献点自己力量。本篇读下来大约10-15分钟,欢迎指正。

 

一.结构解析

最核心(可直接拖拽到新项目中)

 

(拓展cocoapods的拖入) 拖入之前,需要导入AFNetworking,最好利用cocoapods导入,cocoapods导入时

vim Podfile     --->输入i
platform :ios, '8.0'

target "targetName" do

pod 'AFNetworking'

end

(有一点在然后按Esc,并且输入“ :”号进入vim命令模式,然后在冒号后边输入wq)最后pod install。编译一下,拖入项目的类就好了,就不会编译错误。

二.分类讲解

1.Singleton

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

 

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!