前言
本文主要是针对目前我们项目中使用的框架进行一个讲解,使用的框架是MVCS,网络请求用的是YTKNetwork,欢迎各位大佬在下方进行留言,因为现在项目可能要重构,我就是个小白,也没有具体的优化方案。
原理
MVC就不过多的讲解了,我们只是在这个基础上添加了Service层,用来处理网路请求,以及回调的处理,参照的博客地址:
www.jianshu.com/p/8b0d06bd5… blog.csdn.net/wangyanchan…
代码
我自己写了一demo,基本跟目前项目架构类似,目前遇到的问题就是controller里边好多回调方法以及初始化方法,模块之间耦合性太高了,就比如跳转登录页面,然后从登录页面返回的时候需要判断好多条件,每个条件执行的回调方法可能还不一致,不方便维护。demo效果图如下:
M层
@interface HomeModel : ResponseModel
@property (nonatomic, copy) NSString *iconImg;
@property (nonatomic, copy) NSString *iconName;
@property (nonatomic, copy) NSString *iconDesc;
@property (nonatomic, assign) int type;
@end
其中ResponseModel 是继承自JSONModel的
Service层
主要是用来处理请求的,因为YTKNetwork的核心思想是把每一个请求都封装成一个类,然后通过service或者controller层进行调用
下边列一下每个类的作用,以及包括的方法:Protocol 用来初始化数据的方法,因为可能多个页面需要用到,所以写成协议
@protocol HomeDataProtocol <NSObject>
- (void)initWithData:(id)data;
- (void)initWithData:(id)data selectIndex:(NSIndexPath *)indexPath;
@end
这是点击cell对应的加和减的代理方法
@protocol HomeTableViewCellDelegate <NSObject>
- (void)didClickPlusView:(UIButton *)plusView index:(NSInteger)index;
- (void)didClickMinusView:(UIButton *)minusView index:(NSInteger)index;
@end
RequestService 这个主要负责调用Request方法,里边可能会包含到首页模块中用到的方法
@implementation HomeRequestService
+ (void)requestWithUserId:(NSString *)userId
complete:(void(^)(id result,NSError *error))complete{
HomeRequest *request = [[HomeRequest alloc] init];
request.userId = userId;
[request requestComplete:^(BaseRequest * _Nonnull request) {
/// 这里边可以直接处理request返回的结果,但是不应该去处理,因为解析的工作完全可以统一处理
[request handleRequestWithClass:NSArray.class
withComplete:^(id _Nonnull model, NSError * _Nonnull error) {
if (complete) {
model = [HomeModel arrayOfModelsFromDictionaries:model error:&error];
complete(model,error);
}
}];
}];
}
@end
Request 这个继承自YTKNetwork的请求,.m文件需要实现请求的二级路径、是否添加缓存、请求参数等等
@implementation HomeRequest
- (BOOL)enableMockData{
/// 这是我们在猿题库的基础上自己定义了一个方法,是否加载本地的缓存
/// YES代表使用本地缓存,他会从本地查找HomeRequest.json文件进行解析,主要是为了测试数据源的修改
return YES;
}
- (NSString *)requestUrl{
/// 这是请求的二级路径,一级路径需要在程序启动进行配置
return @"XXXXX/XXXX/AA.do";
}
- (YTKRequestMethod)requestMethod{
/// 这是请求的方式
return YTKRequestMethodPOST;
}
- (id)requestArgument{
/// 这是请求的参数
return @{@"userId":_userId};
}
@end
Controller层
主要负责页面UI的展示,以及请求数据,包括代理方法的实现,由于代码量多,只列出部分代码
@interface HomeViewController ()
<
UITableViewDelegate,
UITableViewDataSource,
HomeTableViewCellDelegate
>
@property (nonatomic, strong) UITableView *tableView;
@property (nonatomic, strong) NSMutableArray *dataArray;
@end
- (void)requestData{
__weak typeof(self)weakSelf = self;
[HomeRequestService requestWithUserId:@"test"
complete:^(id _Nonnull result, NSError * _Nonnull error) {
if (!error) {
/// 初始化数据
[weakSelf.dataArray removeAllObjects];
[weakSelf.dataArray addObjectsFromArray:result];
[weakSelf.tableView reloadData];
}else{
/// 处理弹框或者什么的异常处理
}
}];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
HomeTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.delegate = self;
[cell initWithData:self.dataArray[indexPath.row]
selectIndex:indexPath];
return cell;
}
/// 点击加的回调
- (void)didClickPlusView:(UIButton *)plusView index:(NSInteger)index{
HomeModel *model = self.dataArray[index];
model.type++;
[self.tableView reloadRow:index
inSection:0
withRowAnimation:UITableViewRowAnimationNone];
}
- (UITableView *)tableView{
if (!_tableView) {
_tableView = [[UITableView alloc] initWithFrame:CGRectZero
style:UITableViewStylePlain];
_tableView.delegate = self;
_tableView.dataSource = self;
_tableView.backgroundColor = [UIColor redColor];
[_tableView registerClass:[HomeTableViewCell class] forCellReuseIdentifier:identifier];
}
return _tableView;
}
View层就不过的叙述,就是UITableViewCell的创建
基类
BaseViewContoller 和ResponseModel 就不多数了,主要说下BaseRequest类,里边一共3个方法,是否加载本地缓存、发起请求、解析返回json@interface BaseRequest : YTKRequest
/// 这个方法是否使用本地缓存,true代表使用
- (BOOL)enableMockData;
/// 最底层发起请求的方法 (所有请求都需要走这个方法)
/// @param complete 返回结果
- (void)requestComplete:(void(^)(BaseRequest *request))complete;
/// 最底层处理返回结果的方法 (所有返回结果都会走这个方法)
/// @param clsName 需要处理的类
/// @param complete 返回结果
- (void)handleRequestWithClass:(id)clsName withComplete:(void(^)(id model,NSError *error))complete;
@end
至于实现的话就是调用YTKNetwork的方法和调用jsonModel的一个解析方法就不在过多叙述
总结
优点
1,项目架构还是比较清晰的,而且也很好理解,上手容易。
2,减少了好多判断,比如请求参数的判断,这个交给了YTKNetwork,返回数据解析的判断,这个交给了JSONModel,而且还可以针对某个请求单独添加缓存。
3,可以单独配置某个请求是否用本地json,在接口还未实现的时候可以提取开发,只要有结构即可。
缺点
1,如果页面UI复杂,事件交互也比较多,那么Controller层代码量会暴增加,大部分都是delegate方法和getter方法,目前正在考虑如何剥离。
2,项目类会比较多,因为每个请求都是一个单独的类,目前项目大概100个接口左右,光请求的类就100+还不算service层,这个随着项目变大不知道是否会有影响。
3,模块和模块之间的耦合度还是很高,目前的架构还不适合模块的解耦。