iOS-老生常谈MVC、MVP、MVVM
2020-04-17 本文已影响0人
Simple_Code
MVC(apple版)
image.png视图(View):用户界面.
控制器(controller):业务逻辑
模型(Model): 数据
C层主要代码:
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellID: String = "CellID"
var cell: UITableViewCell?
cell = tableView.dequeueReusableCell(withIdentifier: cellID)
if cell == nil {
cell = UITableViewCell(style: .subtitle, reuseIdentifier: cellID)
}
var model = MVCModel()
model = dataArray[indexPath.row]
cell?.textLabel?.text = model.title
cell?.detailTextLabel?.text = model.detail! + String(indexPath.row)
return cell!
}
V使用的事系统自带的UITableViewCell
M层代码:
struct MVCModel: Convertible {
var title: String?
var detail: String?
static func arrayModel() -> [MVCModel] {
let array: [[String: Any]] = [
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
]
return array.kj.modelArray(MVCModel.self)
}
}
实现效果
image.png
结论
如上代码可以看出V
和M
是完全独立的、所有的逻辑处理都在C
层
优点:View、Model可以重复利用,可以独立使用
缺点:Controller的代码过于臃肿
MVC(变种)
image.pngC层主要代码
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cellID: String = "CellID"
var cell: MVCCell?
cell = tableView.dequeueReusableCell(withIdentifier: cellID) as? MVCCell
if cell == nil {
cell = MVCCell(style: .subtitle, reuseIdentifier: cellID)
}
var model = MVCModel()
model = dataArray[indexPath.row]
cell?.model = model
return cell!
}
V层主要代码:
var model: MVCModel? {
didSet {
guard let tempModel = model else {
return
}
titleLabel.text = tempModel.title! + "变种"
detailLabel.text = tempModel.detail! + "变种"
}
}
M层代码:
struct MVCModel: Convertible {
var title: String?
var detail: String?
static func arrayModel() -> [MVCModel] {
let array: [[String: Any]] = [
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
["title":"MVC",
"detail":"detail"],
]
return array.kj.modelArray(MVCModel.self)
}
}
实现效果:
image.png
结论:
如上代码可以看出V
是拥有M
的、数据复制逻辑处理都在V
层
优点:对Controller进行瘦身,将View内部的细节封装起来了,外界不知道View内部的具体实现
缺点:View依赖于Model
MVP
image.pngC层代码
class MVPViewController: UIViewController {
var presenter: MVPPresenter?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
presenter = MVPPresenter(vc: self)
}
}
P层代码
class MVPPresenter: NSObject {
var viewController: UIViewController?
init(vc : UIViewController) {
super.init()
viewController = vc
setUp()
}
func setUp() {
// 创建View
let mView = MVPView()
viewController?.view.addSubview(mView)
mView.snp.makeConstraints { (make) in
make.left.top.right.equalToSuperview()
make.height.equalTo(600)
}
// 赋值数据
mView.titleLabel.text = MVPModel.model().title
mView.imageView.image = UIImage(named: MVPModel.model().image!)
}
}
V层代码
class MVPView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
addSubView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
lazy var imageView: UIImageView = {
let imageView = UIImageView()
return imageView
}()
lazy var titleLabel: UILabel = {
let label = UILabel()
label.text = "MVC变种"
label.textColor = UIColor.HEX(hex: 0x000000)
label.font = UIFont.boldSystemFont(ofSize: 24)
label.numberOfLines = 1
return label
}()
}
extension MVPView {
func addSubView() {
addSubview(imageView)
addSubview(titleLabel)
imageView.snp.makeConstraints { (make) in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(200)
make.height.equalTo(100)
}
titleLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.centerY.equalTo(imageView.snp.bottom).offset(20)
}
}
}
M层代码
struct MVPModel: Convertible {
var title: String?
var image: String?
static func model() -> MVPModel {
let dict: [String: Any] = ["title":"龙妈",
"image":"long.jpg"]
return dict.kj.model(MVPModel.self)
}
}
MVVM
image.pngC层代码
import UIKit
class MVVMViewController: UIViewController {
var viewModel: MVVMViewModel?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
viewModel = MVVMViewModel(vc: self)
}
}
MV层代码
import UIKit
class MVVMViewModel: NSObject {
var viewController: UIViewController?
@objc dynamic var title: String?
@objc dynamic var image: String?
init(vc : UIViewController) {
super.init()
viewController = vc
setUp()
}
func setUp() {
// 创建View
let mView = MVVMView()
viewController?.view.addSubview(mView)
mView.snp.makeConstraints { (make) in
make.left.top.right.equalToSuperview()
make.height.equalTo(600)
}
// 赋值数据
mView.viewModel = self
title = MVVMModel.model().title
image = MVVMModel.model().image
}
}
V层代码
import UIKit
class MVVMView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
addSubView()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var viewModel: MVVMViewModel? {
didSet {
self.kvoController.observe(viewModel, keyPath: "title", options: .new) { (observe, object, change) in
let newValue = change["new"] as? String
self.titleLabel.text = newValue
}
self.kvoController.observe(viewModel, keyPath: "image", options: .new) { (observe, object, change) in
let newValue = change["new"] as? String
self.imageView.image = UIImage(named: newValue!)
}
}
}
lazy var imageView: UIImageView = {
let imageView = UIImageView()
return imageView
}()
lazy var titleLabel: UILabel = {
let label = UILabel()
label.textColor = UIColor.HEX(hex: 0x000000)
label.font = UIFont.boldSystemFont(ofSize: 24)
label.numberOfLines = 1
return label
}()
}
extension MVVMView {
func addSubView() {
addSubview(imageView)
addSubview(titleLabel)
imageView.snp.makeConstraints { (make) in
make.centerX.centerY.equalToSuperview()
make.width.equalTo(200)
make.height.equalTo(100)
}
titleLabel.snp.makeConstraints { (make) in
make.centerX.equalToSuperview()
make.centerY.equalTo(imageView.snp.bottom).offset(20)
}
}
}
M层代码
struct MVVMModel: Convertible {
var title: String?
var image: String?
static func model() -> MVVMModel {
let dict: [String: Any] = ["title":"龙妈",
"image":"long.jpg"]
return dict.kj.model(MVVMModel.self)
}
}
有点:MVVM解决了Controller的代码过于臃肿的问题、并且V和M完全解耦。