文档章节

Let’s discuss MVVM for iOS

hejunbinlan
 hejunbinlan
发布于 2016/01/13 09:39
字数 1009
阅读 16
收藏 0

Some say that as you progress as a software developer you undergo specific stages -

First, you’re glad you’ve made contribution to the code. You go around telling people that you created that glossy red button but you’re too shy to show your own code. You’re also happy that your code works and doesn’t cause fire accidents.

My head is on fire!!

Then, you start writing code that you can actually read yourself a few weeks later.

And then, you write neater code, share them online, and work with other developers.

And finally, you want write beautiful code. Code that reminds you of birds chirping in a lush green valley, clear blue sky, more like poetry. In short, a code that is clean, testable, reusable etc.

What about me? I’m still in the second stage, but hey!..a man can dream!

So recently, I’ve been obsessed with writing simpler code. My first target was the ViewController. If you’ve developed apps for iOS, you’ll know that ViewControllers are easily the most bloated file in the project. It handles a lot more code than necessary — ViewLogic, Model Logic, View Layout, WebService, Delegates etc., the list goes on and this is too much already.

If you dig a little deeper, you’ll find that there is something wrong with the design pattern. MVC. Massive View Controller some call it. It’s a design pattern and a standard approach to build iOS apps. At its heart, it’s a very simple design and a good idea. Here is the design -

In this design pattern, the controller separates the model from the view so that each can change independently. If we didn’t have such a decoupling then every time the model changed, the view would need to change as well.

MVC almost just works, however, as apps get larger, it is easy to wander off MVC, the controller gets bloated and it eventually becomes harder to test.

MVVM to the rescue

Lets look at this alternative pattern, MVVM. It stands for Model-View-ViewModel and it comes from Microsoft. It is quite similar to MVC, formalizes the tightly coupled nature of the View and Controller and introduces a new component.

Wait-.. isn’t this MVC but reworded? Nope. There is a difference. The views still don’t hold references to Model, but neither do Controllers. Instead, there is a new component called ViewModel.

The ViewModel encapsulates data/properties that the view can bind to and any validation logic and actions that can be performed. Typically, the ViewModel interacts with the model by invoking methods in the model classes. The ViewModel then provides data from the model in a form that the view can easily use. In this pattern we are essentially taking the state of our app and putting it into a ViewModel.

For the ViewModel to participate in two-way data binding with View, its properties must raise a PropertyDidChange notification, so that the View gets notified and can change its objects accordingly.

Benefits of MVVM

  • The ViewModel is an excellent place to put your validation logic for user input, view presentation logic, network requests. As a result, the ViewController files become far less bloated.

  • Also, the View-ViewController component is completely isolated from the model. So during development, one developer can work on the UI part of the screen and another can take care of the logic for the screen, independently and concurrently.

  • It is easy to redesign the UI without messing with the model logic since they are both completely isolated. As long as you link appropriate properties to the ViewModel, you can swap view components in and out. This gives more freedom to experiment with the UI.

  • For Universal apps, both iPad and iPhone ViewControllers can interact with the same ViewModel.

  • It’s easier to test. Developers can create unit tests for ViewModel and model without the View.

Enough talk. Let’s get our hands dirty

Let’s see how we implement MVVM in code. We’re going to build a simple iOS app that fetches photos from Flickr.

Here’s the PhotosViewController

 RSPhotosViewController ()

 (nonatomic, strong) RSPhotosViewModel *viewModel;

 (weak, nonatomic) IBOutlet UICollectionView *photosCollectionView;

Notice that the ViewController owns the ViewModel instance. The ViewModel is nothing but a subclass of NSObject. It has only one photosArray property. Here’s how its .h file looks like.

 RSPhotosViewModel : NSObject

 (nonatomic, strong) NSMutableArray *photosArray;

 (void)updatePhotos;

The ViewModel.m file will handle fetching the images from Flickr.

To bind the properties of the ViewModel to the ViewController, I’m going useKVO (Key-Value Observing).

But if you’ve ever used KVO, chances are that you’ve run into various kinds of issues. The API isn’t great and forgetting to remove an observer may result in memory leaks or—even worse—crashes. Thankfully, Facebook’sKVOController library solves those annoying issues with KVO.

So let’s set up the observers. The ViewController is going to observe changes to the photosArray property. Any changes to it, will reload thephotosCollectionView.

 (void)setupObservers
{
 [_KVOController observe:self.viewModel keyPath:@"photosArray" options:NSKeyValueObservingOptionNew block:^(id observer, id object, NSDictionary *change) {
 [self.photosCollectionView reloadData];
 }];

}

If you run the app now, you’ll notice that KVO still doesn’t trigger. The code[photosArray addObjectsFromArray:photos] won’t fire KVO yet. You have to use proxy for collections — mutableArrayValueForKey: .

From the NSKeyValueCoding Protocol Reference

Returns a mutable array proxy that provides read-write access to an ordered to-many relationship specified by a given key.

So your code should look like this,

[self fetchImagesCompletionBlock:^(NSArray *photos) {
 dispatch_async(dispatch_get_main_queue(), ^{
 [self.photosArray removeAllObjects];
 [[self mutableArrayValueForKeyPath:@"photosArray"] addObjectsFromArray:photos];

 });
 } failureBlock:^(NSError *error) {
 NSLog(@"ERROR : %@", error);
 }];

That’s it. Run your app, KVO will fire and voila! that’s MVVM for you.

And so…

Although there might be a slight increase in the amount of code, the complexity has decreased significantly. Even if the amount of code increases a little, there are way too many benefits in this pattern — A worthwhile tradeoff.

You can grab the complete code here.


本文转载自:https://medium.com/@ramshandilya/lets-discuss-mvvm-for-ios-a7960c2f04c7#.7r3l2dh7q

上一篇: MVVM 介绍
hejunbinlan
粉丝 42
博文 596
码字总数 21569
作品 0
浦东
高级程序员
私信 提问
iphone中自定义Universal Framework

大家好, 我有很强烈的欲望来写一点关于这个主题的文章,因为在网络当中关于这个主题的信息实在少得可怜。而且,大多数情况下是错误的或信息不完整,是有误人子弟的感觉。如果你想为iphone写...

长平狐
2012/08/13
1K
0
iOS FrameW Create

http://db-in.com/blog/2011/07/universal-framework-iphone-ios-2-0/ Universal Framework iPhone iOS (2.0) Hello my friends, Due to some bugs and questions with the old tutorial, I’......

晨曦之光
2012/05/28
208
0
EasyIOS 2.0 发布,基于 MVVM 的 IOS 开发框架

全新基于MVVM(Model-View-ViewModel)编程模式架构,开启EasyIOS开发函数式编程新篇章。 EasyIOS 2.0类似AngularJs,最为核心的是:MVVM、ORM、模块化、自动化双向数据绑定、等等 关于有疑问什...

墨水
2014/07/30
9.7K
9
[C++][IO]fstream用法

fstream用法 1. 打开文件 在fstream类中,有一个成员函数open(),就是用来打开文件的,其原型是: void open(const char* filename,int mode,int access); 参数: filename:  要打开的文件...

guitar_zp
2011/08/09
0
0
EasyIOS 2.1 发布,优化网络请求与ORM操作

EasyIOS 2.1发布 此版本相较2.0更新内容如下: 1.优化ORM操作 ,丰富数据库查询方法 2.修改网络请求,选用大家熟悉的AFNetworking 移除 MKNetWorkKit 3.增加正则表达式操作类 4.集成更加友好...

墨水
2014/09/12
2.9K
0

没有更多内容

加载失败,请刷新页面

加载更多

Cesium中级4 - 空间数据可视化(二)

Cesium中文网:http://cesiumcn.org/ | 国内快速访问:http://cesium.coinidea.com/ Viewer中的Entity功能 让我们看看Viewer为操作entities提供出来的功能函数。 选中和描述 点击Viewer中的e...

Cesium中文网
5分钟前
0
0
Linux-CentOS7 安装VMware Workstation

Linux-CentOS7 安装VMware Workstation 太极之道关注0人评论1605人阅读2018-10-17 14:36:22 Linux-CentOS7 安装VMware Workstation 12 1、下载VMware 衔接地址 http://www.vmware.com/produc......

linjin200
8分钟前
0
0
centos7.5 部署flask+nginx+uwsgi+python3

centos7.5 部署flask+nginx+uwsgi+python3 ## uwsgi [uwsgi] master = true max-requests = 6000 processes = 6 threads = 6 chmod-socket = 664 thunder-lock = true buffer-size = 32768 #......

丁典
12分钟前
0
0
BigData NoSQL —— ApsaraDB HBase数据存储与分析平台概览

一、引言 时间到了2019年,数据库也发展到了一个新的拐点,有三个明显的趋势: 越来越多的数据库会做云原生(CloudNative),会不断利用新的硬件及云本身的优势打造CloudNative数据库,国内以阿...

阿里云官方博客
17分钟前
0
0
好代码是什么样的?

简评: 好代码是什么样的?相信不同的人会有不同的看法,正如「一千个读者,就有一千个哈姆雷特」,关键在于你有没有自己的标准。 这篇文章是我个人很喜欢的一家公司 - Atomic Spin 的 blog...

极光推送
17分钟前
2
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部