正在传递参数视图模型或协议

is passing argument a viewmodel or a protocol

代码取自 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 覆盖了 SwitchWithTextCellDelegateSwitchWithTextCellDelegate

的一些默认行为

接下来,作者通过传递 viewModel 作为参数来配置单元格:

SettingsViewController.swift

let viewModel = MinionModeViewModel()
cell.configure(withDataSource: viewModel, delegate: viewModel)
return cell

然而,在SwitchWithTextTableViewCellconfigure方法的参数是SwitchWithTextCellDataSourceSwitchWithTextCellDelegate

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 的新手。有人可以解释一下吗

  1. SwitchWithTextTableViewCell configure方法的dataSourcedelegate的名称和含义是什么?他们是 External Parameter Names.

  2. 为什么 configure 方法的传递参数类型不同:view model vs protocols 类型

协议定义了采用 objects 实现的行为(它们不是覆盖行为 - 通常)。

在这个例子中,SwitchWithTextCellDataSourceSwitchWithTextCellDelegatesMinionModelViewModel继承(领养)的protocols。为了使这更有意义,请考虑您可能有另一个结构:

struct EvilVillanViewModel: SwitchWithTextCellDataSource {
  var title: "Evil Villian Model!!!"
  var switchOn = false
}

因为这个结构也采用了 SwitchWithTextCellDataSource,它可以在代码期望实现 SwitchWithTextCellDataSourceclass/struct 的任何地方互换——因为它知道它会有一个标题和一个 switchOn 值——因为协议要求它。没有它你的代码将无法编译。

所以....在 configure(withDataSource dataSource: SwitchWithTextCellDataSource...) 中,您可以轻松地传入 EvilVillanViewModel 结构或 MinionModelViewModel,一切都会完美运行。当代码块引用 dataSource.title 时,它知道您传递给它的任何内容都有一个 title,因为它必须符合 SwitchWithTextCellDataSource 协议。

而这只是协议力量的开始!希望这对您有所帮助!

首先,MinionModeViewModel 没有覆盖 SwitchWithTextCellDelegate 和 SwitchWithTextCellDelegate 的默认行为。

术语覆盖与继承一起使用。 例子

class A {
  func someFunction() {
  }
}
class B:A {
  override func someFunction() {
  }
}

此处 class B 是 class A 的子class,因此如果 class B 应该提供与其 class A 不同的方法 someFunction 实现它应该覆盖它并提供不同的实现。

协议不同。有点抽象class。协议只是一组规则。 因此,当某些 class 或结构符合协议时,这意味着它们应该实现协议定义中规定的所有必需方法或属性。

示例:

protocol SwitchWithTextCellDelegate {

  func onSwitchTogleOn(on: Bool)

  var switchColor: UIColor {get}
}

现在,任何符合 SwitchWithTextCellDelegate 协议的结构或 class 都应该实现 onSwitchToggleOn 方法,并且还应该有一个 属性 switchColor,后者将有一个 getter.

就像你所做的那样:

extension MinionModeViewModel: SwitchWithTextCellDelegate {
    func onSwitchTogleOn(on: Bool) {
    }

    var switchColor: UIColor {
        return someColor
    }
}

方法说明

1. func configure(withDataSource dataSource: SwitchWithTextCellDataSource, delegate: SwitchWithTextCellDelegate?)

dataSource:在这个参数中我们可以传递任何class或者符合协议SwitchWithTextCellDataSource protcol

的结构

delegate:在这个参数中我们可以传递任何class或者符合协议SwitchWithTextCellDelegate

的结构

现在,教程的作者在两个参数中传递了相同的对象可能会让人感到困惑。为什么不将其作为单个参数传递?

let viewModel = MinionModeViewModel()
cell.configure(withDataSource: viewModel, delegate: viewModel)

因为这里的 MinionModeViewModel 同时符合 SwitchWithTextCellDataSource 和 SwitchWithTextCellDelegate 协议,所以我们可以在两个参数中传递相同的对象。但是这种方法可以灵活地传递任何符合这些协议的对象。