Author: Charles Zhu
Summary: a sample project practising MVVM
之前已经初步了解了一些MVVM的概念,需要在实践中体会这种设计模式,并理解“响应式”带来的优越性。
考虑到最近一直在做网盘类产品,于是决定:获取网盘的内容,并可以浏览内容。如果是文件夹的话,则可以点击查看内容。这样,就相当于实现了一个小型的文件查看器。
另外需要说明的,这里的网盘其实是一个带有系统的SD卡,自身带有AP,可以无线连接访问。同时,提供了API接口获取相关的数据。
MVVM 的角色分配
视图无疑是用UITableView
, 控制器自然选择UITableViewController
,自然这里需要建立一个ViewModel
来监视一切变化并把这种变化传递给控制器。
已知的VM任务
- 获取文件夹列表
VM需要知道当前所在的路径。另外获取到的数据需要重组:比如去掉隐藏文件,进行排序等。这个操作可以封装在某个数据访问层。 - cell的点击操作
对于文件,需要把文件内容显示出来(为了方便,这里只对图片文件显示)。
控制器的任务
显示页面,以及点击cell时的页面切换。
VM的内容
UITableView
的dataSource
dataSource相应的接口需要由VM来实现。在实现cell的时候,cell上的文件名也要通过VM来获取- 数据获取的时机
一般是在VM的信号didBecomeActiveSignal中去注册相应的事件。当事件完成后(获取列表任务),发送更新signal去通知控制器更新页面,因此在控制器中也要注册更新signal收到时相应的事件。整个伪代码逻辑://ViewController @weakify(self) [self.viewModel.updatedContentSignal subscribeNext:^(id x) { @strongify(self); [self.tableView reloadData]; }]; //ViewModel self.updatedContentSignal = [[ RACSubject subject] setNameWithFormat:@"%@_MasterVC",self.directory]; self.flashCommand = [[RACCommand alloc] initWithSignalBlock:^RACSignal *(id input) { return [RACSignal defer:^RACSignal *{ //get content list //finish data fetching and send signal [(RACSubject *)self.updatedContentSignal sendNext:nil]; return nil; }]; }]; @weakify(self) [self.didBecomeActiveSignal subscribeNext:^(id x) { @strongify(self); [self.flashCommand execute:[NSNull null]]; }];
Cell的点击
由于有文件和文件夹的区别,cell无法在storyboard中创建2个push的segue,所以先利用对于文件夹的点击在UITableView
的点击delegate事件中进行操作,而文件的点击则通过performSegueWithIdentifier
来实现。
总结
总体来说,实践基本按循MVVM的原则来进行,控制器中的内容变得很清爽,基本上只包含对view的控制,和VM的通信则是通过响应式的方式实现的。同时VM中包含了很多数据处理的内容,基本上逻辑的部分都转移到了VM中进行。在这种情况下,一个controller就要配一个VM,不知道会不会又造成VM的臃肿?
Comments