模式1 — MVC
MVC是iOS开发中最常用的一种设计模式,模型-视图-控制器,即 Model-View-Controller,下图就是对MVC的最好的解释,斯坦福大学公开课也详细描述了这一模式,你可以戳 这里 去学习。
简单理解就是 Model 持有数据,View 显示与用户交互的界面,而 Controller 来调解 Model 和 View 之间的交互。
从上图来看就是以下三点:
1、Model 和 View 不能相互通信,只能通过 Controller 传递。
2、Controller 可以调用 Model,而Model 只能通过 Notification 和 KVO 机制与 Controller 间接通信。
3、Controller通过outlet直接操作View,而View 通过 action 向 Controller 报告事件的发生。
MVC的不足之处就是会导致你的Controller变得越来越臃肿,所以对于做比较大型的项目来说,MVVM或者是一个更好的选择!
模式2 — MVVM
相比于MVC来说,MVVM多了一个View Model层,因为我们用MVC时通常把网络请求或者一些业务逻辑都放在Controller里面,导致Controller变的臃肿,View Model 就起到了为Controller瘦身的作用。简单来说,就是API请求完数据,解析成model,之后在viewModel中转化成能够直接被视图层使用的数据,交付给前端。
废话不多说,直接上代码。
这是我写的demo的目录结构。
@interface ViewModel ()
@property (nonatomic, strong) NSMutableArray * dataSource;
@end
@implementation ViewModel
+ (NSString *)keyPaht {
return @"dataSource";
}
- (void)getData {
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
manager.requestSerializer.timeoutInterval = 15;
manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
NSString *urlString = @"http://www.xzt1698.com/service.asmx/HomePageInfo";
[manager GET:urlString parameters:@{@"townid": @""} progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) {
NSDictionary *dic = [NSJSONSerialization JSONObjectWithData:[[[XMLDictionaryParser sharedInstance] dictionaryWithParser:responseObject][@"__text"] dataUsingEncoding:NSUTF8StringEncoding] options:NSJSONReadingMutableLeaves error:nil][@"result"];
self.dataSource = [[NSDictionary dictionaryWithDictionary:dic][@"publishInfoList"] mutableCopy];
} failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
}];
}
- (NSInteger)rowsOfSection:(NSInteger)section {
return self.dataSource.count;
}
- (NSMutableArray *)cellDataWithIndexPath:(NSIndexPath *)indexPath {
NSDictionary *dict = self.dataSource[indexPath.row];
NSString *img = dict[@"publishImg"];
NSString *title = dict[@"publishTitle"];
NSString *time = dict[@"publishTime"];
return [@[img, title, time] mutableCopy];
}
ViewModel 主要做的就是网络请求与数据处理,网络请求用的是第三方的 AFNetworking,请求到的数据 用 cellDataWithIndexPath 自定义的方法对数据进行处理。
@interface ViewController ()
@property (weak, nonatomic) IBOutlet UITableView *tableView;
@property (nonatomic, strong) ViewModel *viewModel;
@end
@implementation ViewController
- (ViewModel *)viewModel {
if (!_viewModel) {
_viewModel = [[ViewModel alloc] init];
}
return _viewModel;
}
- (void)viewDidLoad {
[super viewDidLoad];
self.tableView.tableFooterView = [[UIView alloc]initWithFrame:CGRectZero];
[self.viewModel getData];
[self.viewModel addObserver:self forKeyPath:[ViewModel keyPaht] options:NSKeyValueObservingOptionNew context:nil];
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSString *,id> *)change context:(void *)context {
[self.tableView reloadData];
}
- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath {
return 100;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
return [self.viewModel rowsOfSection:section];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
MVVMTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MVVMTableViewCell"];
cell.data = [self.viewModel cellDataWithIndexPath:indexPath];
return cell;
}
- (void)dealloc {
[self.viewModel removeObserver:self forKeyPath:[ViewModel keyPaht]];
}
@end
这么一看,ViewController是不是变的很清爽呢,因为把数据请求和业务逻辑分离出去的缘故,我们需要用KVO的方式来监听ViewModel是否发生了变化,当发起请求后,ViewModel中的自定义处理数据的方法会帮我们把数据处理好并返回给我们,就达到了我们想要的结果。(别忘记移除观察者哦!)
demo的运行效果如下(API是随便抓取的,不用在意哦!����)
模式3 — MVP
从字面意思来理解,MVP 即 Model View Presenter(模型 视图 协调器),P就是 protocol 协议层,通过数据和状态来更新 View。菜鸟博主经验不足,并没有用过这种架构,等到时机成熟会再来更新的!当然还有 另一种架构 VIPER ,这个就更没用过啦,好啦,今天就写到这里了,有时间会来更新的!