代码取自Protocol Oriented MVVM,这就是ViewModel
的样子:
struct MinionModeViewModel: SwitchWithTextCellDataSource {
var title = "Minion Mode!!!"
var switchOn = true
}
extension MinionModeViewModel: SwitchWithTextCellDelegate {
func onSwitchTogleOn(on: Bool) {
if on {
print("The Minions are here to stay!")
} else {
print("The Minions went out to play!")
}
}
var switchColor: UIColor {
return .yellowColor()
}
}
我理解这一部分。基本上,MinionModeViewModel
覆盖了SwitchWithTextCellDelegate
和SwitchWithTextCellDelegate
的某些默认行为
接下来,作者通过传递viewModel
作为参数来配置单元格:
SettingsViewController.swift
let viewModel = MinionModeViewModel()
cell.configure(withDataSource: viewModel, delegate: viewModel)
return cell
但是,在SwitchWithTextTableViewCell
,configure
方法的参数为SwitchWithTextCellDataSource
和SwitchWithTextCellDelegate
func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?) {
self.dataSource = dataSource
self.delegate = delegate
label.text = dataSource.title
switchToggle.on = dataSource.switchOn
// color option added!
switchToggle.onTintColor = delegate?.switchColor
}
我是Swift的新手。有人可以解释一下
dataSource
中delegate
方法的名称及其含义configure
和SwitchWithTextTableViewCell
是什么。他们是External Parameter Names
。
为什么configure
方法的传递参数类型不同:view model
vs protocols
类型
答案 0 :(得分:2)
首先,MinionModeViewModel不会覆盖SwitchWithTextCellDelegate和SwitchWithTextCellDelegate的默认行为。
术语覆盖与继承一起使用。 实施例
class A {
func someFunction() {
}
}
class B:A {
override func someFunction() {
}
}
这里的类B是类A的子类,因此如果类B应该提供方法someFunction的不同实现而不是类A,它应该覆盖它并提供不同的实现。
协议不同。它是一种抽象的类。协议只是一套规则。 因此,当某个类或结构符合协议时,它意味着它们应该实现协议定义中声明的所有必需的方法或属性。
示例:
protocol SwitchWithTextCellDelegate {
func onSwitchTogleOn(on: Bool)
var switchColor: UIColor {get}
}
现在任何符合协议SwitchWithTextCellDelegate的结构或类都应该实现onSwitchToggleOn方法,并且还应该有一个具有getter的属性switchColor。
就像你做过的那样:
extension MinionModeViewModel: SwitchWithTextCellDelegate {
func onSwitchTogleOn(on: Bool) {
}
var switchColor: UIColor {
return someColor
}
}
方法说明
1. func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?)
dataSource :在此参数中,我们可以传递符合协议SwitchWithTextCellDataSource protcol的任何类或结构
委托:在此参数中,我们可以传递符合协议SwitchWithTextCellDelegate的任何类或结构
现在,教程的作者在两个参数中都传递了相同的对象,这可能会令人困惑。为什么不将它作为单个参数传递?
let viewModel = MinionModeViewModel()
cell.configure(withDataSource: viewModel, delegate: viewModel)
这是因为MinionModeViewModel符合SwitchWithTextCellDataSource和SwitchWithTextCellDelegate协议,因此我们可以在两个参数中传递相同的对象。但是这种方法可以灵活地传递任何符合这些协议的对象。
答案 1 :(得分:1)
协议定义采用对象实现的行为(通常不会覆盖行为)。
在此示例中,SwitchWithTextCellDataSource
和SwitchWithTextCellDelegates
为protocols
MinionModelViewModel
继承(已采用)。为了更有意义,请考虑您可能有另一个结构:
struct EvilVillanViewModel: SwitchWithTextCellDataSource {
var title: "Evil Villian Model!!!"
var switchOn = false
}
由于此结构也采用SwitchWithTextCellDataSource
,因此只要代码期望实现class
的{{1}} / struct
,它就可以互换 - 因为它知道它将具有SwitchWithTextCellDataSource
title和switchOn值 - 因为协议需要它。没有它,您的代码将无法编译。
所以....在configure(withDataSource dataSource: SwitchWithTextCellDataSource...)
中,您可以轻松传入EvilVillanViewModel
结构或MinionModelViewModel
,一切都会完美无缺。当代码块引用dataSource.title
时,它知道你传递的内容是title
,因为它必须符合SwitchWithTextCellDataSource
协议。
这只是协议能力的开始!希望这有帮助!