我已经对此做了很多研究,所以我会告诉你我认为它做了什么,然后希望有人可以告诉我它实际上做了什么。
我试图通过学习教程(link)来理解MVVM模式。我会把所有代码都放在这里以防万一有人想把它放到Xcode中。
我的视图模型名为GreetingViewModel,它采用协议并包含我不理解的这行代码:
protocol GreetingViewModelProtocol: class {
var greeting: String? { get }
var greetingDidChange: ((GreetingViewModelProtocol) -> ())? { get set }
init(person: Person)
func showGreeting()
}
class GreetingViewModel : GreetingViewModelProtocol {
let person: Person
var greeting: String? {
didSet {
self.greetingDidChange?(self)
}
}
// what does line do???
var greetingDidChange: ((GreetingViewModelProtocol) -> ())?
required init(person: Person) {
self.person = person
}
@objc func showGreeting() {
self.greeting = "Hello" + " " + self.person.firstName + " " + self.person.lastName
}
}
在视图控制器(下面)中,当self.viewModel = viewModel
执行时,它会在var viewModel
的属性观察者中运行代码。然后将函数(GreetingViewModelProtocol) -> ()
分配给var greetingDidChange
。
class GreetingViewController : UIViewController {
let showGreetingButton = UIButton()
@IBOutlet weak var greetingLabel: UILabel!
var viewModel: GreetingViewModelProtocol! {
didSet {
self.viewModel.greetingDidChange = { [unowned self] viewModel in
self.greetingLabel.text = viewModel.greeting
}
}
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func viewDidLoad() {
super.viewDidLoad()
let model = Person(firstName: "David", lastName: "Blaine")
let viewModel = GreetingViewModel(person: model)
self.viewModel = viewModel
showGreetingButton.backgroundColor = UIColor.red
showGreetingButton.tintColor = UIColor.black
showGreetingButton.setTitle("Show Greeting", for: .normal)
showGreetingButton.addTarget(self.viewModel, action: #selector(GreetingViewModel.showGreeting), for: .touchUpInside)
showGreetingButton.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(showGreetingButton)
let buttonTop = NSLayoutConstraint(item: showGreetingButton, attribute: NSLayoutAttribute.top, relatedBy: NSLayoutRelation.greaterThanOrEqual, toItem: view, attribute: NSLayoutAttribute.topMargin, multiplier: 1.0, constant: 20)
let buttonLeading = NSLayoutConstraint(item: showGreetingButton, attribute: NSLayoutAttribute.leading, relatedBy: NSLayoutRelation.equal, toItem: view, attribute: NSLayoutAttribute.leadingMargin, multiplier: 1.0, constant: 0.0)
showGreetingButton.contentEdgeInsets = UIEdgeInsetsMake(2, 2, 2, 2)
NSLayoutConstraint.activate([buttonTop, buttonLeading])
}
}
此时,我相信这只是表示greetingDidChange拥有一个函数,该函数接受采用GreetingViewModelProtocol
协议的任何类对象并且不返回任何内容。 UI完成加载,看起来像这样:
当我点击显示问候语按钮时,会调用GreetingViewModel.showGreeting()
,然后执行var greeting
上的属性观察者(self.greetingDidChange?(self)
)将GreetingViewModel
发送到此神秘的代码行我不明白。
这会导致此属性观察者执行:
var viewModel: GreetingViewModelProtocol! {
didSet {
self.viewModel.greetingDidChange = { [unowned self] viewModel in
self.greetingLabel.text = viewModel.greeting
}
}
}
然后执行其余代码并显示消息:
我认为因为viewModel
是GreetingViewModel
,var viewModel
属性观察者中的闭包设置为self.greetingLabel.text = GreetingViewModel.greeting
。在我的神秘代码行var greetingDidChange: ((GreetingViewModelProtocol) -> ())?
和viewModel.didSet
中的代码之间似乎存在某种关系,但它会让我感觉它是如何工作的。
我是否接近,有人会善意向我解释这里发生了什么?
另外,我的简单模型是:
struct Person {
let firstName: String
let lastName: String
}