我写了一个非常简单的MVC程序,带有标签和按钮。标签显示计数器的值,按下按钮时该计数器会递增。
下面的代码给出了模型文件和视图控制器文件。模型文件是一个类。 该代码有效。
这是模型文件:
import Foundation
protocol MVCModelDelegate {
var message: String {get set}
}
// when I change class to struct
// delegate is set to nil
// causing the program not to update the label
class Model {
var delegate: MVCModelDelegate?
var counter: Int
var message: String {
didSet {
delegate?.message = model.message
}
}
init(counter: Int, message: String) {
self.counter = counter
self.message = message
}
}
// create instance
var model = Model(counter: 0, message: "")
// counting
func incrementCounter() {
model.counter += 1
model.message = "Counter Value: \(model.counter)"
}
这是视图控制器文件
import Cocoa
class ViewController: NSViewController, MVCModelDelegate {
// communication link to the model
var model1 = model
var message = model.message {
didSet {
didUpdateModel(message: message)
}
}
override func viewDidLoad() {
super.viewDidLoad()
self.model1.delegate = self
}
// update display
func didUpdateModel(message: String) {
Label1.stringValue = model1.message
}
// Label
@IBOutlet weak var Label1: NSTextField! {
didSet {
Label1.stringValue = " counter not started"
}
}
// Button
@IBAction func testButton(_ sender: NSButton) {
incrementCounter()
}
}
问题:我现在想要更改模型文件的代码以使用结构代替类,因为这个非常简单的程序不需要类的所有功能。但是一旦我改变了struct的类。该程序仍然运行,但标签未更新,因为委托变量设置为nil并且永远不会获得另一个值。
问题:我错过了什么? swift文档鼓励尽可能使用struct。我没有在代码中看到将类转换为结构的问题。
答案 0 :(得分:2)
结构是不可变的,它不像类一样通过引用传递,而是通过值传递。这意味着当你做
时var model1 = model
您正在创建model
的副本。
修改model1
不会将更改传播到model
,因此您在incrementCounter
中所做的一切都不会反映在您的视图控制器中。
如果您希望incrementCounter
影响viewController,它必须使用viewController实例中的模型。
如果您打算在更新此模型时共享model
属性并更改标签值,那么struct不是最佳选择。