版权声明:本文为博主原创文章,未经博主授权不得转载。

项目github地址 https://github.com/zhangjiahuan8888/mvvmDemo/tree/master

开篇

MVC Model-View-Controller是一个用来组织代码的权威范式。Apple甚至是这么说的。在MVC下,所有的对象被归类为一个model,一个view,或一个controller。Model持有数据,View显示与用户交互的界面,而View Controller调解Model和View之间的交互。 MVVM MVVM的出现主要是为了解决在开发过程中Controller越来越庞大的问题,变得难以维护,所以MVVM把数据加工的任务从Controller中解放了出来,使得Controller只需要专注于数据调配的工作,ViewModel则去负责数据加工并通过通知机制让View响应ViewModel的改变。

效果图

源码分析

1.Model模块

首先是model层的代码,创建MovieModel类,继承自NSObject。设置几个属性movieName、year、imageUrl、detailUrl(用于跳转)

  1. #import <Foundation>
  2. @interface MovieModel : NSObject
  3. @property (strong, nonatomic) NSString *movieName;
  4. @property (strong, nonatomic) NSString *year;
  5. @property (strong, nonatomic) NSURL *imageUrl;
  6. @property (strong, nonatomic) NSString *detailUrl;
  7. @end
ViewController模块

ViewController里面是用来从MovieViewModel中获取数据信息然后展示到UITableView的cell上面,和点击单元格的页面跳转

  1. #import "HomeViewController.h"
  2. #import "MovieViewModel.h"
  3. #import "MovieCell.h"
  4. @interface HomeViewController ()<UITableViewDataSource>
  5. @property (nonatomic,strong) NSArray *modelArray;
  6. @end
  7. @implementation HomeViewController
  8. - (void)viewDidLoad {
  9. [super viewDidLoad];
  10. self.title = @"电影首页";
  11. self.view.backgroundColor = [UIColor redColor];
  12. UITableView *tableView = [[UITableView alloc] initWithFrame:self.view.bounds style:UITableViewStylePlain];
  13. tableView.dataSource = self;
  14. tableView.delegate = self;
  15. tableView.rowHeight = 80;
  16. [self.view addSubview:tableView];
  17. [tableView registerClass:[MovieCell class] forCellReuseIdentifier:@"MovieCell"];
  18. //初始化MovieViewModel,设置成功(returnBlock)和失败的回调(errorBlock),getMovieData去请求数据,请求数据成功即回调上一步设置的returnBlock,请求失败则回调errorBlock
  19. MovieViewModel *viewModel = [[MovieViewModel alloc] init];
  20. viewModel.returnBlock = ^(id returnValue){
  21. _modelArray = returnValue;
  22. [tableView reloadData];
  23. };
  24. viewModel.errorBlock = ^(id errorCode){
  25. NSLog(@"%@",errorCode);
  26. };
  27. [viewModel getMovieData];
  28. }
  29. #pragma mark - UITableViewDataSource
  30. - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
  31. return _modelArray.count;
  32. }
  33. - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{
  34. MovieCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MovieCell"];
  35. cell.model = _modelArray[indexPath.row];
  36. return cell;
  37. }
  38. - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{
  39. MovieViewModel *movieViewModel = [[MovieViewModel alloc] init];
  40. [movieViewModel movieDetailWithPublicModel:_modelArray[indexPath.row] WithViewController:self];
  41. }
  42. @end
View模块

view这里跟MVC中子类化UITableViewCell一样,将model数据传进来,复写setModel方法给视图传递数据

  1. #import "MovieModel.h"
  2. @interface MovieCell : UITableViewCell
  3. @property (nonatomic,strong) MovieModel *model;
  4. @end
  5. #import "MovieCell.h"
  6. #import "UIImageView+AFNetworking.h"
  7. @interface MovieCell()
  8. @property (nonatomic,strong) UILabel *nameLabel;
  9. @property (nonatomic,strong) UILabel *yearLabel;
  10. @property (nonatomic,strong) UIImageView *imgView;
  11. @end
  12. @implementation MovieCell
  13. - (instancetype)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier{
  14. self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
  15. if (self) {
  16. _imgView = [[UIImageView alloc] initWithFrame:CGRectMake(15, 10, 40, 60)];
  17. [self.contentView addSubview:_imgView];
  18. _nameLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 10, 200, 20)];
  19. [self.contentView addSubview:_nameLabel];
  20. _yearLabel = [[UILabel alloc] initWithFrame:CGRectMake(70, 50, 100, 20)];
  21. _yearLabel.textColor = [UIColor lightGrayColor];
  22. _yearLabel.font = [UIFont systemFontOfSize:14];
  23. [self.contentView addSubview:_yearLabel];
  24. }
  25. return self;
  26. }
  27. - (void)setModel:(MovieModel *)model{
  28. _model = model;
  29. _nameLabel.text = _model.movieName;
  30. _yearLabel.text = _model.year;
  31. [_imgView setImageWithURL:_model.imageUrl];
  32. }
  33. @end
ViewModel模块

ViewModel是最重要的模块: 1.这里面进行了数据的网络请求,并将数据转换成model放在一个数组中,调用_returnBlock将model数组传递给viewController进行数据源的处理 2.将页面跳转的逻辑放在ViewModel中,点击单元格进行页面跳转的时候直接在- (void)tableView:(UITableView )tableView didSelectRowAtIndexPath:(NSIndexPath )indexPath中调用MovieViewModel的该方法即可

  1. #import <Foundation>
  2. #import "MovieModel.h"
  3. #import <UIKit>
  4. typedef void (^ReturnValueBlock) (id returnValue);
  5. typedef void (^ErrorCodeBlock) (id errorCode);
  6. @interface MovieViewModel : NSObject
  7. @property (nonatomic,copy) ReturnValueBlock returnBlock;
  8. @property (nonatomic,copy) ErrorCodeBlock errorBlock;
  9. //获取电影数据
  10. - (void)getMovieData;
  11. //跳转到电影详情页
  12. - (void)movieDetailWithPublicModel: (MovieModel *)movieModel WithViewController: (UIViewController *)superController;
  13. @end
  14. #import "MovieViewModel.h"
  15. #import "NetworkService.h"
  16. #import "MovieModel.h"
  17. #import "MovieViewController.h"
  18. @implementation MovieViewModel
  19. - (void)getMovieData{
  20. [NetworkService requestWithURL:@"/v2/movie/coming_soon" params:nil success:^(id result) {
  21. NSLog(@"%@",result);
  22. NSArray *subjects = result[@"subjects"];
  23. NSMutableArray *modelArr = [NSMutableArray arrayWithCapacity:subjects.count];
  24. for (NSDictionary *subject in subjects) {
  25. MovieModel *model = [[MovieModel alloc] init];
  26. model.movieName = subject[@"title"];
  27. model.year = subject[@"year"];
  28. NSString *urlStr = subject[@"images"][@"medium"];
  29. model.imageUrl = [NSURL URLWithString:urlStr];
  30. model.detailUrl = subject[@"alt"];
  31. [modelArr addObject:model];
  32. }
  33. _returnBlock(modelArr);
  34. } failure:^(NSError *error) {
  35. NSLog(@"%@",error);
  36. _errorBlock(error);
  37. }];
  38. }
  39. - (void)movieDetailWithPublicModel: (MovieModel *)movieModel WithViewController: (UIViewController *)superController{
  40. MovieViewController *movieVC = [[MovieViewController alloc] init];
  41. movieVC.url = movieModel.detailUrl;
  42. [superController.navigationController pushViewController:movieVC animated:YES];
  43. }
  44. @end
 

MVVM架构简单使用的更多相关文章

  1. MVVM架构~目录

    回到占占推荐博客索引 MVVM在概念上是真正将页面与数据逻辑分离的模式,在开发方式上,它是真正将前台代码开发者(JS+HTML)与后台代码开发者分离的模式(asp,asp.net,php,jsp).在 ...

  2. MVVM架构~Knockoutjs系列之验证机制的引入

    返回目录 对于Knockoutjs本身来说,没有提供验证模块,不过,有第三方的扩展,就像你为jquery库作extensions一样,这讲中我将介绍一个Knockout插件扩展,knockout.va ...

  3. MVVM架构~使用boxy和knockoutjs实现编辑功能

    返回目录 这个功能我认为非常有用,尤其在后台管理系统中,它对用户来说,使用体验这块非常不错,下面是它的截图

  4. ReactiveCocoa常见操作方法介绍/MVVM架构思想

      1.ReactiveCocoa常见操作方法介绍. 1.1 ReactiveCocoa操作须知 所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中, ...

  5. MVVM架构~knockoutjs系列之表单添加(验证)与列表操作源码开放

    返回目录 本文章应该是knockoutjs系列的最后一篇了,前几篇中主要讲一些基础知识,这一讲主要是一个实际的例子,对于一个对象的添加与编辑功能的实现,并将项目源代码公开了,共大家一起学习! knoc ...

  6. WPF MVVM 架构 Step By Step(6)(把actions从view model解耦)

    到现在为止,我们创建了一个简单的MVVM的例子,包含了实现了的属性和命令.我们现在有这样一个包含了例如textbox类似的输入元素的视图,textbox用绑定来和view model联系,像点击but ...

  7. iOS MVVM架构总结

    为什么使用MVVM iOS中,我们使用的大部分都是MVC架构.虽然MVC的层次明确,但是由于功能日益的增加.代码的维护,使得更多的代码被写在了Controller中,这样Controller就显得非常 ...

  8. [转]MVVM架构~mvc,mvp,mvvm大话开篇

    MVP 是从经典的模式MVC演变而来,它们的基本思想有相通的地方:Controller/Presenter负责逻辑的处理,Model提供数据,View负 责显示.作为一种新的模式,MVP与MVC有着一 ...

  9. [Vue入门及介绍,基础使用、MVVM架构、插值表达式、文本指令、事件指令]

    [Vue入门及介绍,基础使用.MVVM架构.插值表达式.文本指令.事件指令] 1)定义:javascript渐进式框架 ​ 渐进式:可以控制一个页面的一个标签,也可以控制一系列标签,也可以控制整个页面 ...

随机推荐

  1. Service Receiver Activity 之间的通信

    一.Activity与Service 1. 通过Intent,例子如下: Intent intent = new Intent(this, Myservice.class); // intent .p ...

  2. python 添加进度条

    安装: pip install tqdm使用: from tqdm import tqdm import time for i in tqdm(rang(10)): time.sleep(0.1)

  3. Jmeter(八)Jmeter监控tomcat

    1.配置tomcat的配置文件conf/tomcat-users.xml 2. 在“线程组”上右键“添加”--“配置元件”--“HTTP授权管理器”,这里主要是让JMeter能够通过Tomcat的基本 ...

  4. PAT 1151 LCA in a Binary Tree[难][二叉树]

    1151 LCA in a Binary Tree (30 分) The lowest common ancestor (LCA) of two nodes U and V in a tree is ...

  5. mysql lock

    http://blog.chinaunix.net/uid-21505614-id-289450.html http://bbs.csdn.net/topics/340127237 http://ww ...

  6. The Air Jordan 4 Oreo Remastered would be re-released in 2015

    May be the Jordan 4 Oreo probably the most anticipated pair among the remastered Jordans for 2015? W ...

  7. 学习Android开发看那些书好?

    学习一样新事物或许有多种方式,报培训班,看视频,向高手请教等等,但一本好书往往可以让你少走很多弯路,事半功倍. 下面推荐几本个人觉得搞Android开发值得一读的书籍. Head First Java ...

  8. 2016-2017 National Taiwan University World Final Team Selection Contest A - Hacker Cups and Balls

    题目: Dreamoon likes algorithm competitions very much. But when he feels crazy because he cannot figur ...

  9. hdu1403 Longest Common Substring

    地址:http://acm.split.hdu.edu.cn/showproblem.php?pid=1403 题目: Longest Common Substring Time Limit: 800 ...

  10. Winter-2-STL-B Brackets 解题报告及测试数据

    Time Limit:2000MS     Memory Limit:65536KB Description Given a string consisting of brackets of two ...