一·Controller层
先上代码
代码语言:objective-c复制@interface Controller()
@property(nonatomic, strong) UITableView *tableView;
@end
@implementation Controller
- (void)viewDidload {
[super viewDidload];
初始化UI
懒加载
[self.view addSubView:xxxx];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
_cell = [tableView dequeueReusableCellWithIdentifier:addCellId forIndexPath:indexPath];
_cell.model = [APIManager manager].backPackModel[indexPath.row];
return _cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
[tableView deselectRowAtIndexPath:indexPath animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return self.dataArray.count;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
MVCTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:reuserId forIndexPath:indexPath];
// 不合理
cell.model = self.dataArray[indexPath.row];
return cell;
}
相信很多人都有写过这段代码 delegate & dataSource 代理方法 导致了VC的沉重
@end
问题来了回到工程项目需求,每个cell都有增加减少按钮 而且需要有选中效果在View层.意味着MVC架构模式中 我在View层对Model进行了修改.
再者Action操作视图逻辑代码是放在C层或V层 最终导致C层随着需求会慢慢变大变臃肿
再回过头来看项目工程目录导致VC过重的原因因素
·繁重的UI 例如tableView CollectionView
·业务逻辑 如下面的全选效果
·网络请求
·代理方法
优化代码
代码语言:objective-c复制封装一个继承自NSObject的类,遵循DataSource代理
@interface Controller()
@property(nonatomic, strong) UITableView *tableView;
@property(nonatomic, strong) YourDataSource *dataSource;
@end
@implementation Controller
- (void)viewDidload {
self.dataSource = [YourDataSource alloc]initWithIdentifier:reuserId
configBlock:^(yourCellClass *cell, Model *model, NSIndexPath *indexPath) {
cell.model = model; //这一句代码代表了MVC模式中的 Model->View 这一单层通道
}
[self.view addSubview:self.tableView];
self.tableView.dataSource = self.dataSource;
[self.dataSource addDataArray:[SingleManager manage].userListArr];
}
@end
到这减少了 DataSource 所需要实现的代码
这里不给出DataSource的封装代码 需要源码的可以加我 936101005 点个赞 ~ 拒绝伸手
二·Model层
Model层玩法就很多了,这里我通常使用单例保存在内存中看 -> 《iOS-使用GCD单例创建管理对象》
第二种玩法是通过Swift混编,我们来对比一下Model层的不同
定义
代码语言:javascript复制OC层
@interface Model : NSObject
@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *imageUrl;
@property (nonatomic, copy) NSString *num;
@property (nonatomic, strong) NSArray <UserModel *> *userList;
@end
@interface UserModel : NSObject
@property (nonatomic, copy) NSString *userId;
@property (nonatomic, copy) NSString *group;
@end
代码语言:javascript复制Swift层
先定义结构体 model结构
struct ModelBean: Coable {
let name: String
let imageUrl: String?
let num: Int
let userList : [UserModelBean]
}
struct UserModelBean: Coable {
let userId: String
let group: String
}
解析
我的上一篇文章写了关于数据与模型绑定的文章《NSArray与Model模型》,不熟悉的可以回过头看一看。
代码语言:javascript复制 OC层
for (int i = 0; i<temArray.count; i ) {
Model *m = [Model modelWithDictionary:temArray[i]];
[self.dataArray addObject:m];
}
但通常的,我会使用MJExtention封装好的三方框架来解析数据
mj_objectArrayWithKeyValuesArray
代码语言:javascript复制Swift层
通常解析数据会根据后台的数据结构返回来的JSON进行匹配
swift会有点麻烦 我们拿一个 数据里嵌套数组来作为例子
@objc public class Model: NSObject {
init(bean: ModelBean) {
name = bean.name
imageUrl = bean.imageUrl
num = bean.num
userList = bean.userList?.map{ .init(bean: $0)} ?? []
}
@objc public let name: String
@objc public let imageUrl: String?
@objc public let num: Int
@objc public let userList : [UserModelBean]
}
@objc public class UserModelBean: NSObject {
init(bean: UserModelBean){
userId = bean.userId ?? ""
gourp = bean.gourp ?? ""
}
@objc public let userId: String?
@objc public let gourp: String?
}
三·View层
MVC架构中model层数据传给cell通过setter与数据进行通信
代码语言:objective-c复制@interface Cell : UITableViewCell
@property (nonatomic, strong) Model *model;
@end
@implementation Cell
但是外界数据模型没有一起变化, 暴露一个接口给外界刷新UI 导致了高偶合问题
- (void)setNum:(int)num {
_num = num;
self.model.num = self.numLabel.text;
}
View 和 Model 进行了绑定 //到此双向绑定完成
- (void)setModel:(Model *)model { //setter Model 代表了MVC架构中的View -> Model view展示model数据
_model = model;
self.num = model.num;
self.Name = model.name;
self.xxx = model.xxx;
}
@end
四·MV? 架构 (Model和UI之间的消息通讯方式)
在上面我们把DataSource麻烦的代码交给了封装的DataSource类中,但是还剩下一个Delegate代理没解决
MVC (最快上手架构)
MV-Protocal (适用于复杂的多层回调)
MV-Block (适用于简单的单层回调)
创建一个数据提供层Present 也可以成为称为代理,来减少Controller的负担
代码语言:objective-c复制@protocal PresentDelegate <NSObject>
- (void)addBtnWithNum:(int)num indexPath:(NSIndexPath *)indexPath;
- (void)reloadUi;
@end
@interface Present: NSObject <PresentDelegate>
@property (nonatomic, weak) id<PresentDelegate> delegate;
@end
@implementation Present
- (void)addBtnWithNum:(int)num indexPath:(NSInexPath *)indexPath {
@synchronized (self) {
if (indexPath.row < [SingleManage manage].userList.count) {
Model *model = [SingleManager manage].userListArr[indexPath.row];
model.num = num;
}
}
if (self.delegate && [self.delegate respondsToSelector:@selecotr(reloadUI)]) {
[self.delegate reloadUI];
}
}
@end
View层的setter方法就可以优化成
代码语言:javascript复制@interface Cell: UITableViewCell
@property (nonatomic, weak) id<PresentDelegate> delegate;
@property (nonatomic, strong) NSIndexPath* indexPath;
@end
@implementation
- (void)setNum:(int)num {
_num = num;
if (self.delegate && [self.delegate respondsToSelector:@selector(didClickNum:indexPath:)]) {
[self.delegate didClickNum:self.numLabel indexPath:self.indexPath];
}
}
@end
那么最终Controller层可以写成这样
代码语言:objective-c复制 __weak typeof(self) weakSelf = self;
self.dataSource = [[DataSource alloc] initWithIdentifier:reuserId configureBlock:^(MVPTableViewCell *cell, Model *model, NSIndexPath *indexPath) {
// 代理 model --> UI
cell.numLabel.text = model.num;
cell.nameLabel.text = model.name;
cell.indexPath = indexPath;
cell.delegate = weakSelf.pt;
}];
[self.dataSource addDataArray:[SingleManager manager].userList];
// UI
[self.view addSubview:self.tableView];
self.tableView.dataSource = self.dataSource;
self.pt.delegate = self;