做iOS开发有一段时间,接触了许多的网络请求组件。但是很多网络请求组件对业务的耦合性比较高,很难脱离业务层。对网络请求组件进行了一些优化,实现了接口化及模块化使得该组件更易用,易用扩展,低耦合。
1.模块详解
1.1 结构简图
1.2 各模块解析
config
- JCNetWorkingEnvironmentConfigure 域名及环境的全局配置
- JCNetWorkingProtocolManager 模型转换和缓存功能实例化单例(此类对两层协议进行类绑定)
采用协议的方式进行实现可将接口统一,之后如果需要修改sdk只需要修改实现类即可,不会让sdk代码入侵业务代码之中
protocol
- JCNetWorkingBusinessServiceProtocol 请求服务协议
- JCNetWorkingModelProtocol 模型转换协议(主要实现字典与模型之间的转换)
- JCNetWorkingCacheProtocol 缓存功能协议(主要实现数据缓存)
- JCNetWorkingServiceProtocol 网络请求的主要实现协议
custom
- JCNetWorkingBusinessService 基础服务协议实现类,绑定了功能组件
- JCNetWorkingModelTool 模型转换实现类
- JCNetWorkingCacheTool 缓存功能实现类
- JCNetWorkingServiceTool 网络请求实现类
- JCNetWorkingClient 此类使用AFNetWorking对网络请求的post get update进行了实现
- JCNetWorkingRequest 网络请求工具请求对象(封装和定义了请求参数及缓存功能)
model
- JCNetWorkingParameterModel 基础请求体模型
- JCNetWorkingResponseModel 基础返回体模型
- JCNetWorkingErrorResponseModel 错误返回体模型
tool
- NSString+JCNetWoringUtil 将json字典直接转化为格式好的json字符串
- NSDictionary+JCNetWoringUtil 字典去空工具
1.3 使用的第三方sdk
- AFNetworking (网络请求SDK)
- MJExtension (模型转换SDK)
- YYCache (数据缓存SDK)
2.架构思想解析
2.1 接口化
组件使用协议统一外部接口,让我们只需要关注内在的功能实现。只要关注协议对象对统一接口的实现即可,而不需要关注该对象在整个组件之间的逻辑,这样在我们需要更换SDK或更改协议对象实现方式的时候就会更加方便和便捷。此处以模型协议JCNetWorkingModelProtocol做为例子进行讲解。
我们定义一个需要统一接口的协议:JCNetWorkingModelProtocol
#import <Foundation/Foundation.h>
@protocol JCNetWorkingModelProtocol <NSObject>
// 模型变成字典
+ (NSDictionary *)configDictWithResponseModel:(id)responseObject;
// 将数据转换成模型
+ (id)configModelWithResponseObject:(id)responseObject class:(Class)cls;
@end
我们定义一个实现该协议的对象:JCNetWorkingModelTool
#import <Foundation/Foundation.h>
#import "JCNetWorkingModelProtocol.h"
@interface JCNetWorkingModelTool : NSObject <JCNetWorkingModelProtocol>
@end
#import "JCNetWorkingModelTool.h"
#import "MJExtension.h"
#import "NSDictionary+JCNetWoringUtil.h"
@implementation JCNetWorkingModelTool
+ (NSDictionary *)configDictWithResponseModel:(id)responseObject {
return [[responseObject mj_keyValues] removeNullValues];
}
+ (id)configModelWithResponseObject:(id)responseObject class:(Class)cls {
if ([responseObject isKindOfClass:[NSArray class]]) {
return [cls mj_objectArrayWithKeyValuesArray:responseObject];
}
id responseModel = [cls mj_objectWithKeyValues:responseObject];
return responseModel;
}
@end
在JCNetWorkingModelTool协议对象中,我们使用了第三方SDK MJExtension进行模型转换的实现,如果我们发现MJExtension出现了严重的bug,不再适合工程使用的时候,只需要替换问题的SDK并实现协议方法即可,耦合性变得很低。protocol文件夹下的其他接口协议同样适用。
2.2 模块化
在测试项目中书写了一个首页网络请求模块。不同的开发人员只要集成JCNetWorkingManager组件,并书写各自的网络服务协议便可按照各自的模块进行开发,使各个模块之间没有任何耦合。
我们定义一个模块的网络层服务协议
#import <Foundation/Foundation.h>
#import "JCNetWorkingParameterModel.h"
@protocol JCHomeSerivceProtocol <NSObject>
/**
*
* @brief 启动页
*
*/
- (void)requestStartUpWithParameter:(JCNetWorkingParameterModel *)parameterModel Success:(RequestSuccess)success failure:(RequestFailure)failure;
@end
我们定义一个模块的网络层服务协议实现类JCHomeService,并实现协议方法即可。
#import "JCHomeService.h"
static NSString *const kStartPic = @"/zbs/index/startpic"; //启动图片
@implementation JCHomeService
- (void)requestStartUpWithParameter:(JCNetWorkingParameterModel *)parameterModel Success:(RequestSuccess)success failure:(RequestFailure)failure {
JCNetWorkingRequest *request = [JCNetWorkingRequest requestWithDomainType:JCDomainTypeHome path:kStartPic parameterModel:parameterModel responseClass:[JCHomeStarPageResponseModel class]];
request.netWorkingModelProtocolClass = self.netWorkingModelProtocolClass;
request.netWorkingCacheTool = self.netWorkingCacheTool;
[self sendRequest:request success:success failure:failure];
}
@end
3.使用详解
3.1 工程环境及域名配置
在正式使用项目的时候我们需要配置功能环境,以达到自动切换请求环境的目的。
在Appdelegate书写转换代码,这样只要我们切换了编译环境。我们网络请求模块的域名就会自动修改为对应的环境域名。
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
// Override point for customization after application launch.
#ifdef TEST_ENV
[[JCNetWorkingEnvironmentConfigure showJCEnvironmentConfigure] setEnvironmentType:JCNetWorkingEnvironmentTypeTest];
#else
[[JCNetWorkingEnvironmentConfigure showJCEnvironmentConfigure] setEnvironmentType:JCNetWorkingEnvironmentTypeOnline];
#endif
return YES;
}
在JCNetWorkingEnvironmentConfigure中对网络组件的总体域名进行定义并分类。在.h文件中定义了两个分类枚举分别为环境枚举,域名枚举。
typedef NS_ENUM(NSUInteger, JCNetWorkingEnvironmentType) {
JCNetWorkingEnvironmentTypeTest,
JCNetWorkingEnvironmentTypeOnline
};
typedef NS_ENUM(NSInteger , JCDomainType) {
JCDomainTypeDefault,
JCDomainTypeHome
};
在JCNetWorkingEnvironmentConfigure.m中主要是定义具体域名。
- (void)setEnvironmentType:(JCNetWorkingEnvironmentType)environmentType {
_environmentType = environmentType;
switch (environmentType) {
case JCNetWorkingEnvironmentTypeTest:
{
_HTTPHost = @"http://www.baidu.com";
_HomeHost = @"http://www.google.com";
}
break;
case JCNetWorkingEnvironmentTypeOnline:
{
_HTTPHost = @"http://www.baidu.com";
_HomeHost = @"http://www.google.com";
}
break;
default:
break;
}
}
- (NSString *)configPathWithDomainTypeDefault:(JCDomainType)domainTypeDefault path:(NSString *)path {
switch (domainTypeDefault) {
case JCDomainTypeDefault:
{
return [[JCNetWorkingEnvironmentConfigure showJCEnvironmentConfigure].HTTPHost stringByAppendingString:path];
}
break;
case JCDomainTypeHome:
{
return [[JCNetWorkingEnvironmentConfigure showJCEnvironmentConfigure].HomeHost stringByAppendingString:path];
}
break;
}
}
3.2 网络请求模块书写
该模块的教程书写同2.2 模块化中的具体实现即可。
3.3 具体使用
在具体的控制器中定义协议服务对象,并发起请求即可。
- (void)requestStarPage {
[self.homeService requestStartUpWithParameter:[JCHomeStarPageParameterModel new] Success:^(JCHomeStarPageResponseModel * responseModel, BOOL isCache) {
NSLog(@"%@", responseModel);
} failure:^(JCNetWorkingErrorResponseModel *responseModel) {
NSLog(@"%@", responseModel);
}];
}
- (JCHomeService *)homeService {
if (!_homeService){
_homeService = [JCHomeService new];
}
return _homeService;
}