Loading [MathJax]/jax/output/CommonHTML/config.js
前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >iOS-MVVM 模式简单演练

iOS-MVVM 模式简单演练

作者头像
用户1890628
发布于 2018-05-10 09:36:15
发布于 2018-05-10 09:36:15
88300
代码可运行
举报
文章被收录于专栏:Objective-CObjective-C
运行总次数:0
代码可运行

本篇只是简单介绍一下MVVM的大致模式,每个人对每种架构模式有自己的理解,本文也是单纯的从获取新闻列表数据,并将其显示到界面上而已。暂时不做过多的考虑。


MVVM 简介

看下MVVM大致模式图 :

相当于在ViewViewControllerModel之间多了一层ViewModel。那么多出这层起到了什么作用呢?好处又好在哪里呢?

简单说就是如果数据结构有变动,而View层没有变动的话,那么只要处理ViewModel中的业务逻辑就可以了。ViewModel的主要作用就是处理数据处理一些小的业务逻辑等一些作用。

下面以一个新闻列表为例,展示结果如下图 :


文件结构

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- Main
    - AppDelegate.h
    - AppDelegate.m
    - main.m
- News
    - Controller
        - QQNewsViewController.h
        - QQNewsViewController.m
    - ViewModel
        - QQNewsListViewModel.h
        - QQNewsListViewModel.m
        - QQNewsViewModel.h
        - QQNewsViewModel.m
    - View
        - QQNewsCell.h
        - QQNewsCell.m
    - Model
        - QQNews.h
        - QQNews.m
- Tool
    - NetWork
        - QQNetworkManager.h
        - QQNetworkManager.m
        - QQNetworkManager+QQNews.h
        - QQNetworkManager+QQNews.m

文件结构说明

  • QQNewsViewModel 单条新闻视图模型(处理业务逻辑)
  • QQNewsListViewModel 新闻列表视图模型(获取数据、加工数据)
  • QQNetworkManager网络请求工具类
  • QQNetworkManager+QQNews网络请求工具类的分类(专门用于获取新闻列表数据)

获取数据

QQNetworkManager的分类QQNetworkManager+QQNews中定义一个加载新闻数据的方法,供外界调用。

拿到的数据后,简单处理一下,回调到QQNewsListViewModel中。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "QQNetworkManager.h"

@interface QQNetworkManager (QQNews)

- (void)loadNewsDataCompletion:(void (^)(NSArray *dataArray))completion;

@end
代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#import "QQNetworkManager+QQNews.h"

static NSString *const newsURLString = @"http://c.m.163.com/nc/article/headline/T1348647853363/0-10.html";

@implementation QQNetworkManager (QQNews)

- (void)loadNewsDataCompletion:(void (^)(NSArray *))completion {
    
    [[QQNetworkManager sharedManager] qq_request:GET urlString:newsURLString parameters:nil finished:^(id result, NSError *error) {
        if (error) {
            NSLog(@"%s %@", __FUNCTION__, error);
        }
        NSLog(@"%s %@", __FUNCTION__, result);
        
        /**
         * 简单处理数据,只把需要的回调到`QQNewsListViewModel`中
         */
        completion(result[@"T1348647853363"]);
    }];
}

@end

QQNewsListViewModel.h中定义新闻视图模型数组,用来控制QQNewsViewControllerTableView显示的Cell行数及Cell的显示内容。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
QQNewsListViewModel.h

@class QQNewsViewModel;

@interface QQNewsListViewModel : NSObject

/// 新闻`视图模型`数组
@property (nonatomic, strong) NSMutableArray *newsList;

/**
 加载新闻数据

 @param completion completion
 */
- (void)loadNewsDataCompletion:(void (^)(BOOL isSuccessed))completion;

@end

QQNewsListViewModel.m中进行数据加工,将拿到的字典数组转化为视图模型数组

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
QQNewsListViewModel.m

- (void)loadNewsDataCompletion:(void (^)(BOOL))completion {
    
    // 调用`QQNetworkManager+QQNews`中的获取新闻数据的方法
    [[QQNetworkManager sharedManager] loadNewsDataCompletion:^(NSArray *dataArray) {
        
        NSLog(@"%s %@", __FUNCTION__, dataArray);
        
        NSMutableArray *arrayM = [NSMutableArray arrayWithCapacity:dataArray.count];
        
        for (NSDictionary *dict in dataArray) {
            
            QQNews *news = [QQNews mj_objectWithKeyValues:dict];
            [arrayM addObject:[QQNewsViewModel viewModelWithNews:news]];
        }
        
        [self.newsList addObjectsFromArray:arrayM];
        
        // 将结果回调给`QQNewsViewController`,使其进行刷新界面等操作
        completion(YES);
    }];
}

接下来QQNewsViewController中就只持有QQNewsListViewModel,基本主要方法就剩下了TableViewDataSourceDelegate方法了。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
@interface QQNewsViewController ()<UITableViewDataSource, UITableViewDelegate>

/// TableView
@property (nonatomic, strong) UITableView *tableView;
/// 新闻视图模型数组
@property (nonatomic, strong) QQNewsListViewModel *newsListViewModel;

@end

@implementation QQNewsViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    
    [self setupUI];
    [self loadData];
}

#pragma mark - Load Data
- (void)loadData {
    
    [self.newsListViewModel loadNewsDataCompletion:^(BOOL isSuccessed) {
        
        if (!isSuccessed) {
            NSLog(@"%s 没有请求到数据", __FUNCTION__);
        }
        [self.tableView reloadData];
    }];
}

#pragma mark - SetupUI
- (void)setupUI {
    
    self.navigationItem.title = @"新闻列表";
    [self tableView];
}

#pragma mark - UITableViewDataSource
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    return self.newsListViewModel.newsList.count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    
    QQNewsCell *cell = [QQNewsCell newsCellWithTableView:tableView];
    cell.viewModel = self.newsListViewModel.newsList[indexPath.row];
    return cell;
}

QQNewsCell里赋值的方法就可以简化成如下 :

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
- (void)setViewModel:(QQNewsViewModel *)viewModel {
    _viewModel = viewModel;
    
    [self.newsImageView sd_setImageWithURL:viewModel.imgsrc_url];
    self.newsTitleLabel.text = viewModel.news.title;
    self.newsSubTitleLabel.text = viewModel.news.digest;
    self.replyCountLabel.text = viewModel.replyCount_string;
}

imgsrc_urlreplyCount_string都是根据拿到的数据在QQNewsViewModel里面加工处理过的。QQNewsCell不需要关心返回数据需要经过再次处理的事情,安心展示界面就OK了。

接下来QQNewsViewModel就来处理各种业务逻辑了,比如时间跟帖数等等一切不能直接把数据直接显示,需要再加工的事情。

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
QQNewsViewModel.h

/// 新闻数据模型
@property (nonatomic, strong) QQNews *news;
/// 新闻图片URL
@property (nonatomic, strong) NSURL *imgsrc_url;
/// 跟帖数(在此处理)
@property (nonatomic, copy) NSString *replyCount_string;

+ (instancetype)viewModelWithNews:(QQNews *)news;

处理业展示的数据,并可以直接对一些情况方便的进行测试,比如查看跟帖数大于1万人时的显示等等...

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
+ (instancetype)viewModelWithNews:(QQNews *)news {
    
    QQNewsViewModel *viewModel = [[self alloc] init];
    
    viewModel.news = news;
    
    return viewModel;
}

- (NSURL *)imgsrc_url {
    
    return [NSURL URLWithString:self.news.imgsrc];
}

- (NSString *)replyCount_string {
    
    // 测试跟帖数超过1万
//    self.news.replyCount = 23456;
    
    if (self.news.replyCount >= 10000) {
        
        NSString *string = [NSString stringWithFormat:@"%ld万 跟帖", self.news.replyCount / 10000];
        return string;
    }
    return [NSString stringWithFormat:@"%ld 跟帖", self.news.replyCount];
}

如果没有ViewModel层的话,这些事情基本都是要放在CellsetModel方法里面去做。如果Cell界面够复杂的话,Cell内的代码就会超级多。也不是不行,只是不太便于我们进行修改测试等。

本文这种情况用这种MVVM模式无疑是有点用力过猛了。但是我觉得实际开发中,很少能碰到这么简单的业务逻辑的,如果业务逻辑多起来了。这种模式就会突显出它的好处了。

Demo 传送门 : MVVM

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2017.12.03 ,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
如何在复杂TableView界面开发中变得优雅
可见,完整地实现一个UITableView,需要在较多的方法中设定UI逻辑。TabeView结构简单时还好,但当它相对复杂时,比如存在多种TableViewCell,实现时很容易出现界面逻辑混乱,代码冗余重复的情况。在另外的几个protocol方法中,还有更多的这种if else判断,特别是tableView:cellForRowAtIndexPath:方法。
進无尽
2018/09/12
1.3K0
如何在复杂TableView界面开发中变得优雅
iOS-UITableView 详解(一)
iOS-UITableView 详解 (一) ✨建议收藏,用到时候一查就明白了 UITableView可以说是iOS开发中最重要的控件之一,它的使用非常广泛,今天我们来学习UITableView的使
xx_Cc
2018/05/10
1.5K0
iOS开发之微信聊天页面实现
  在上篇博客(iOS开发之微信聊天工具栏的封装)中对微信聊天页面下方的工具栏进行了封装,本篇博客中就使用之前封装的工具栏来进行聊天页面的编写。在聊天页面中主要用到了TableView的知识,还有如何在俩天中显示我们发送的表情,具体请参考之前的博客:IOS开发之显示微博表情,在这儿就不做赘述啦。在聊天页面用到了三对,六种Cell,不过cell的复杂度要比之前的新浪微博(IOS开发之新浪围脖)简单的多。废话少说吧,还是先来几张效果图,在给出实现代码吧。   聊天界面的效果图如下:在下面的聊天界面中中用到了3类
lizelu
2018/01/11
4.3K0
iOS开发之微信聊天页面实现
iOS网络视频下载与播放:两种视频URL格式(m3u8 & mp4)(AVFoundation框架篇·以网易视频为例)
分析网易新闻的视频接口时,单个视频数据其实会包含了两种视频URL格式地址,一个MP4视频URL,一个m3u8视频URL。
陈满iOS
2018/09/10
9.5K0
iOS网络视频下载与播放:两种视频URL格式(m3u8 & mp4)(AVFoundation框架篇·以网易视频为例)
聊聊iOS开发之MVVM的架构设计
而MVVM这种新的代码组织方式就可以解决这些问题,本文就MVVM的架构设计做个简单的个人总结。
進无尽
2018/09/12
8.9K0
聊聊iOS开发之MVVM的架构设计
写给iOS小白的MVVM教程(一): 从MVC到MVVM之一个典型的MVC应用场景
本文讲述了一个典型的列表-详情模型的MVC实现,包括其基本架构、代码实现和注意事项。通过这个实例,展示了如何利用MVC设计模式优化代码结构和提高代码可维护性。同时,也探讨了如何在技术社区中更好地协作和共享知识。
ios122
2018/01/02
2K0
写给iOS小白的MVVM教程(一): 从MVC到MVVM之一个典型的MVC应用场景
Swift-MVVM 简单演练(四)
Swift-MVVM 简单演练(一) Swift-MVVM 简单演练(二) Swift-MVVM 简单演练(三) 前言 这一篇主要写微博的首页布局,及MVVM模式的体会。像微博这种自定义的Cell布局略显复杂一些,我们最好将其拆分出来各个不同的模块来处理比较好一些。不要像之前那样,所有的控件都写在一个cell里面,那样不好处理。虽然说总体上来说,是学习MVVM模式,但是架构都是基于项目而设立的。脱离业务谈什么模式本身就不是很好。凡事有法,但法无定式。依个人习惯去延伸就好。没必要非得说谁的代码就一定是错的。这
用户1890628
2018/05/10
2.4K0
Swift-MVVM 简单演练(一)
Swift-MVVM 简单演练(二) Swift-MVVM 简单演练(三) Swift-MVVM 简单演练(四) 前言 最近在学习swift和MVVM架构模式,目的只是将自己的学习笔记记录下来,方便自己日后查找,仅此而已!!! 本来打算一篇全部搞定的,但是简书每篇文章只能写大约不超过15000字的内容,因此只能分开写了。 如果有任何问题,欢迎和我一起讨论。当然如果有什么存在的问题,欢迎批评指正,我会积极改造的! ---- 这篇文章都写啥 自定义NavgationBar 抽取便利构造函数 初步的下拉刷新/上
用户1890628
2018/05/10
10.7K0
iOS_11_tableViewCell使用alertView变更数据
发布者:全栈程序员栈长,转载请注明出处:https://javaforall.cn/117667.html原文链接:https://javaforall.cn
全栈程序员站长
2022/07/05
5260
iOS_11_tableViewCell使用alertView变更数据
macOS开发之NSTableView的应用详解
    和iOS开发中的UITableView有很大差别,NSTableView并非是一个可滚动的列表视图,其是一个不可滚动、支持多列多行的原始列表视图。若要使NSTableView支持滚动,通常会将其嵌套入NSScrollView控件中。与UITableView类似,NSTableView的数据也是用过DataSource代理来提供,通过Delegate代理来进行表格视图的定制化。在OS X v10.6版本之前,NSTableView中行数据载体视图必须是NSCell的子类,之后版本的OS X支持开发者创建基于View的TableView视图,同样也支持基于Cell的TabelView视图,在开发者,我们可以根据实际需求选择。
珲少
2018/08/15
4.9K0
macOS开发之NSTableView的应用详解
iOS开发之表视图爱上CoreData
  在接触到CoreData时,感觉就是苹果封装的一个ORM。CoreData负责在Model的实体和sqllite建立关联,数据模型的实体类就相当于Java中的JavaBean, 而CoreData的功能和JavaEE中的Hibernate的功能类似,最基本是两者都有通过对实体的操作来实现对数据库的CURD操作。CoreData中的上下文(managedObjectContext)就相当于Hibernate中的session对象, CoreData中的save操作就和Hibernate中的commit,还
lizelu
2018/01/11
2.3K0
iOS开发之表视图爱上CoreData
iOS操作属性列表plist(增删改查)
iOS的存储方式之一——属性列表plist,还是经常见到的,可以很方便的用来管理一些有序的批量数据,特别是用来显示固定的内容到表单上时,不需要在代码中反复地繁琐编写数组,而可以在plist属性列表中进行可视化操作,极为便捷,本文讲解如何创建和使用plist列表,并显示在表单上。
Cloudox
2021/11/23
1.7K0
iOS操作属性列表plist(增删改查)
【iOS开发】路由+协议打造极简 table view 和 collection view 页面
好久没有写东西了,今天来分享一下最近在项目中对UITableView的一种优化写法。
吴老师
2018/09/05
1K0
【iOS开发】路由+协议打造极简 table view 和 collection view 页面
iOS10中Messages独立应用与扩展插件详析
        Messages是iOS系统中原生的信息应用,其既可以通过运营商网络发送短信息,也可以通过互联网进行类似微信类社交软件的即时聊天。但是由于其封闭性与功能的单一,使用其进行即时聊天的用户并不多。随着iOS10系统的推出,或许可以改变这一现状。在iOS10中,Messages的功能被扩展的十分强大,通过Messages,用户可以分享图片,音乐,视频,可以随手涂鸦,使用自定义的表情包,可以进行Apple Pay支付,购物,甚至可以在Messages中玩游戏。并且,上面所提到的这些功能都全面开发出了接口供开发者进行开发与扩展。
珲少
2018/08/15
1.2K0
iOS10中Messages独立应用与扩展插件详析
iOS 二级菜单(UITableView实现)「建议收藏」
首先建立一个cell的类,用于存放cell中的内容 ,继承自uitableviewcell;
全栈程序员站长
2022/06/27
1.3K0
iOS开发-搜索栏UISearchBar和UISearchController
最近项目中用到了搜索栏,所以在网上搜了一些相关的资料学习了一下,现在记录一下,iOS中的搜索栏实现起来相对简单一点,网上也有很多参考资料,不过靠谱的不是很多,很多都是iOS 8.0之前的实现,iOS 8.0上的实现貌似很少看到,看了一些其他人的代码,使用了一下UISearchController感觉还是非常不错的。好了不多说了 ,来点干货吧。 1 UISearchBar和UIDisplayController实现搜索 是网上最常见的也算是最简单的,也有使用Searh Bar Search Displa
roc
2018/03/30
2.5K0
iOS开发-搜索栏UISearchBar和UISearchController
ReactiveCocoa 进阶
所有的信号(RACSignal)都可以进行操作处理,因为所有操作方法都定义在RACStream.h中,因此只要继承RACStream就有了操作处理方法。
零式的天空
2022/03/23
1K0
iOS:分割控制器UISplitViewcontroller
<1>功能:它也是ipad的一个新特性,在屏幕上可以同时显示两个控制器,左边一个,右边一个;左边的为主控制器,右边的为详细控制器,主控制器可以根据需要显示或隐藏。它对于iPhone虽然可以使用,但是不具备同时显示的特点,在iPhone的样式,就是导航控制器切换的模式。
全栈程序员站长
2022/07/05
2.2K0
iOS:分割控制器UISplitViewcontroller
iOS - 开发1年后对MVC新的理解
问题来了回到工程项目需求,每个cell都有增加减少按钮 而且需要有选中效果在View层.意味着MVC架构模式中 我在View层对Model进行了修改.
Wilbur-L
2022/03/10
1.2K1
iOS开发之UITableView联动实现城市选择器
在 iOS开发之城市选择器一文中用两列的UIPickerView实现了城市选择器,今天用两个UITableView来实现一下,首先这种联动在很多地方用得上,而且方法有好几种,我这里选择了个人喜欢的一种方式:弄两个UITableView,让当前控制器管理。这种方式总体思路如下: 1、添加两个UITableView到当前控制器中,分别设置它们的的尺寸,然后拖线到控制器中 2、左边的表格设置数据源和代理为当前控制器,然后显示数据,右边的表格也设置数据源为当前控制器,然后显示数据操作。 3、监听左边表格控制器
YungFan
2018/05/03
2.3K0
iOS开发之UITableView联动实现城市选择器
推荐阅读
相关推荐
如何在复杂TableView界面开发中变得优雅
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验