2017-06-21 9 views
2

プロパティオブザーバをトリガする参照プロパティを取得するにはどうすればよいですか?参照プロパティの迅速なプロパティオブザーバ

私の問題を示すために、私は1つのボタンと1つのラベルを持つシンプルな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を動作させることができたら、私は感謝します。

あなたは ViewControllerクラスが MvcModelDelegateに準拠して作成し、最終的にはあなたが viewDidLoadmodel.delegate = self設定 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 
    } 
} 

次のあなたにデリゲートプロパティを追加MvcModel

protocol MvcModelDelegate { 
    func didUpdateModel(counter:Int) 
} 

のデリゲートを作成することができ

+0

ファイルのあなたの質問への更新などの回答ではないなどのソリューションを投稿してください。これは、将来の訪問者が混乱を理解し、それを避けるためです。 – Bugs

答えて

1

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私のコードは単なる例でした。 print( "counter \(counter)"の新しい値)を 'self.myTextLabel.text = counter.description'のように置き換える必要があります。 –

+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 - モデルファイルをいくつか修正して、クラスから構造体に移動するようにモデルを修正しようとしました(ビューコントローラファイルで変更はありません)。構造体によってクラスを変更すると、プログラムはもはや機能しなくなります。デリゲートの値がnilであるため、実際には "delegate?.didUpdateModel(message:message)"は実行されていないようです。私は、デリゲートプロパティを正しく宣言/初期化しないという問題があると思います。 これを修正するにはどうすればよいですか?これらのトピックを詳細かつ明確にカバーする書籍のアイデアですか? –