2017-07-04 29 views
0

我已經用標籤和一個按鈕編寫了一個非常簡單的MVC程序。標籤顯示按下按鈕時計數器的值增加。Swift:如何將一個類更改爲一個struct

下面的代碼給出了模型文件和視圖控制器文件。模型文件是一個類。 該代碼有效。

這裏是模型文件:

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() 
    } 
} 

問題:我現在想改變模型文件的代碼代替使用結構因爲這個非常簡單的程序不需要一個類的所有功能。但只要我改變了類的結構。該程序仍在運行,但標籤不會更新,因爲委託變量設置爲零,並且永遠不會獲取其他值。

問題:我錯過了什麼? swift文檔鼓勵在可能的情況下使用struct。而且在代碼中我沒有看到將類轉換爲結構的問題。

+0

當您將類更改爲結構時,嘗試添加'mutating func incrementCounter()'。我認爲默認情況下,'value'類型的屬性不能在其實例方法內改變。 – Simon

+0

@Simon。如果[func incrementCounter]是該結構的一個方法,這將工作。 –

回答

2

結構是不可變的,它不像引用類那樣通過引用傳遞,而是通過值傳遞。這意味着當你做

var model1 = model 

您正在創建一個model的副本。

修改model1不會將更改傳播到model,因此您在incrementCounter中所做的所有操作都不會反映在您的視圖控制器中。

如果你想讓你的incrementCounter影響viewController,它必須在你的viewController實例中使用模型。

如果您的意圖是共享model屬性並在更新此模型時更改標籤值,則struct不是最佳選擇。

+0

@Guiseppe Lanza - 你是對的。但從我看到的當我運行程序時,當我按下VC中的按鈕時,計數器在模型中遞增,設置了model.message,didSet運行,但由於委託值爲零,指令是中止,沒有任何東西被傳回給VC。 –

+0

正如我所說的模型和模型1不知道對方。它們是兩種不同的內存分配。修改一個不會影響另一個。這意味着當您修改model1的委託變量var時,這不會在模型中設置,並且當您修改模型中的變量時,它們不會修改model1中的任何變量。 –