2017-06-21 57 views
2

如何獲取引用屬性以觸發屬性觀察者?參考屬性上的swift屬性觀察者

爲了演示我的問題,我用一個按鈕和一個標籤編寫了一個簡單的MVC程序。該按鈕增加模型中的計數器並在計算機視圖控制器中的標籤中顯示計數器的值。

的問題是,計數器增量(在模型中)不觸發didSet觀察者(在視圖控制器)

下面是該模型的文件:

import Foundation 

class MvcModel { 
    var counter: Int 
    var message: String 

    init(counter: Int, message: String) { 
     self.counter = counter 
     self.message = message 
    } 
} 

// create instance 
var model = MvcModel(counter: 0, message: "") 

// counting 
func incrementCounter() { 
    model.counter += 1 
    model.message = "Counter Value: \(model.counter)" 
    //print(model.message) 
} 

這裏是視圖控制器文件:

import Cocoa 

class ViewController: NSViewController { 

    let model1 = model 

    var messageFromModel = model.message { 
     didSet { 
      updateDisplayCounterLabel() 
     } 
    } 

    // update Label 
    func updateDisplayCounterLabel() { 
     DisplayCounterLabel.stringValue = model1.message 
    } 

    // Label 
    @IBOutlet weak var DisplayCounterLabel: NSTextField! { 
     didSet { 
      DisplayCounterLabel.stringValue = "counter not started" 
     } 
    } 

    // Button 
    @IBAction func IncrementButton(_ sender: NSButton) { 
     incrementCounter() 
     print("IBAction: \(model1.message)") 
    } 
} 

我想這個問題是與參考性質(因爲我已經能夠使本工作方案與基於結構的模型)。

如果有人能告訴我如何處理屬性觀察者和引用屬性,並使這種MVC工作,我打算在真正的程序中使用它,我將不勝感激。

+0

請張貼解決方案,答案不是更新你的問題。這是爲了幫助未來的訪問者理解並避免混淆。 – Bugs

回答

1

您可以爲MvcModel

protocol MvcModelDelegate { 
    func didUpdateModel(counter:Int) 
} 

的委託下一次委託屬性添加到MvcModel

class MvcModel { 
    var counter: Int { 
     didSet { 
      delegate?.didUpdateModel(counter: counter) 
     } 
    } 

    var message: String 
    var delegate: MvcModelDelegate? 

    init(counter: Int, message: String) { 
     self.counter = counter 
     self.message = message 
    } 
} 

那麼您做出ViewController類符合MvcModelDelegate最後你設置model.delegate = selfviewDidLoad

class Controller: UIViewController, MvcModelDelegate { 

    let model = MvcModel(counter: 0, message: "hello") 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.model.delegate = self 
    } 

    func didUpdateModel(counter: Int) { 
     print("new value for counter \(counter)") 
    } 

} 
+0

@Noam我根據你的建議編輯了模型和ViewController文件。我不熟悉協議和委託(因爲我只是開始編程)。所以我不確定我是否做出了正確的修改。在任何情況下,程序編譯但標籤不更新,控制檯只顯示IBAction:hello。我需要回到我的書籍並理解邏輯。 –

+0

@ C.Merger我的代碼只是一個例子。你需要用'self.myTextLabel.text = counter.description'來代替'print(「counter \(counter)」)的新值' –

+0

@Noam是的,這就是我所理解的。看起來像計數器更新時不會調用didUpdateModel函數。 –

0

如果有人對此感興趣,請按照Noam建議的代碼。

模型文件:

import Foundation 

    protocol MvcModelDelegate { 
     func didUpDateModel(message: String) 
    } 

    class MvcModel { 
     var counter: Int 
     var message: String { 
      didSet { 
       delegate?.didUpDateModel(message: message) 
      } 
     } 
     var delegate: MvcModelDelegate? 

     init(counter: Int, message: String) { 
      self.counter = counter 
      self.message = message 
     } 
    } 

    // create instance 
    var model = MvcModel(counter: 0, message: "") 

    // counting 
    func incrementCounter() { 
     model.counter += 1 
     model.message = "Counter Value: \(model.counter)" 
    } 
} 

視圖控制器文件

import Cocoa 

class ViewController: NSViewController, ModelDelegate { 
    // communication link to the model 
    var model1 = model 
    var messageFromModel = messageToLabel 

    override func viewDidLoad() { 
     super.viewDidLoad() 
     self.model1.delegate = self 
    } 

    // update display 
    func didUpdateModel(message: String) { 
     //self.Label1.stringValue = model1.message 
     self.Label1.stringValue = messageFromModel 
    } 

    // Label 
    @IBOutlet weak var Label1: NSTextField! { 
     didSet { 
      Label1.stringValue = " counter not started" 
     } 
    } 

    // Button 
    @IBAction func testButton(_ sender: NSButton) { 
     incrementCounter() 
    }  
} 
+0

@Noam - 我試圖修改模型,將其從類中移動到結構中,在模型文件中進行一些調整(在視圖控制器文件中沒有更改)。只要我通過struct改變類,程序不再起作用。事實上,它看起來像「委託?.didUpdateModel(消息:消息)」不執行,因爲委託值是零。我想問題是我不正確地聲明/初始化委託屬性。 你會建議如何解決這個問題?任何關於詳細和清晰地涵蓋這些主題的書的想法? –