1、传统的MVC
可以看出另外每个实体都知道另外两个实体,这显然降低了可重用性当然也不是您在开发中想要的。
2、苹果的MVC
这里View和Model的关系剪断,但是在Controller中会变得很臃肿,Controller中代码量会变得很大。想想将业务逻辑、网络请求、View状态改变还有把addSubView的代码也放在Controller中的,看了眼要修改的Controller是不是想死的心都有了。
3、我的MVC
设计模式不是死,根据自己的需求和理解进行一些改变是必要的,再变也是万变不离其宗,现在的项目的使用的MVC实际上就是对Controller的瘦身。上图是取自iOS Architecture Patterns,这里我直接说我的实现。
我的目录是根据模块进行分解然后在模块目录下创建MVC的文件夹,我不喜欢大的MVC文件目录然后吧相关的类放进对应的文件夹下的。
Model
和你所知MVC中的M是一样的
/
// Model.swift
// Test
//
// Created by 小七 on 2017/9/19.
// Copyright © 2017年 Seven. All rights reserved.
//
import UIKit
struct Model {
var name: String?
}
View
我不会在Controller中写addSunViews这样的代码, 所以这样的代码全在封装带View中了,这里用的Storyboard。我将storyboard放在Controller中纯属个人习惯,我个人认为这个是属于View的
//
// TableViewCell.swift
// Test
//
// Created by 小七 on 2017/9/19.
// Copyright © 2017年 Seven. All rights reserved.
//
import UIKit
class MyTableViewCell: UITableViewCell {
@IBOutlet weak var label: UILabel!
override func awakeFromNib() {
super.awakeFromNib()
// Initialization code
}
override func setSelected(_ selected: Bool, animated: Bool) {
super.setSelected(selected, animated: animated)
// Configure the view for the selected state
}
}
Controller
Controller中含有Request和C->V的数值传递类, 在实际项目中将一部分的业务逻辑代码放在了ViewModel中了(这里的ViewModel并不是MVVM中所表达的意思,只是借鉴了一些思路)
//
// ViewController.swift
// Test
//
// Created by 小七 on 2017/9/19.
// Copyright © 2017年 Seven. All rights reserved.
//
import UIKit
class ViewController: UITableViewController {
lazy private var mViewModel: ViewModel = ViewModel()
lazy private var mRequest: Request = Request()
override func viewDidLoad() {
super.viewDidLoad()
mRequest.request {[weak self] in
self?.tableView.reloadData()
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return mRequest.list.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "MyTableViewCell", for: indexPath) as! MyTableViewCell
mViewModel.loadCellWithModel(mRequest.list[indexPath.row], view: cell)
return cell
}
}
ViewModel
这里做了数据的传递
//
// ViewModel.swift
// Test
//
// Created by 小七 on 2017/9/19.
// Copyright © 2017年 Seven. All rights reserved.
//
import UIKit
class ViewModel: NSObject {
func loadCellWithModel(_ model: Model, view: MyTableViewCell) {
view.label.text = model.name
}
}
Request
网络请求的封装和Model的储存,我的Controller中是不储存Model的
//
// Request.swift
// Test
//
// Created by 小七 on 2017/9/19.
// Copyright © 2017年 Seven. All rights reserved.
//
import UIKit
class Request: NSObject {
var list: [Model] = [Model]()
func request(result: () -> Void){
for _ in 0 ... 20 {
var m = Model()
m.name = "12345"
list.append(m)
}
result()
}
}
后语
实际上MVVM和MVP可以也可以解决C过于臃肿的问题。那为什么没有使用流行的MVVM呢,因为MVVM的实现离不开RX和RAC,主要项目中没有使用它们所以就没有直接引入MVVM(这个理由确实牵强 = =!),还有建议使用的所有第三方库最好自己进行封装下,不然在换库的时候会留下悔恨的泪水。
git地址go go
谢谢观赏,这里是我在项目中对MVC的理解,希望多多指正