2017-07-04 9 views
0

非常に単純なMVCプログラムをラベルとボタンで作成しました。ラベルには、ボタンを押したときにインクリメントされるカウンタの値が表示されます。Swift:クラスを構造体に変更する方法

次のコードは、モデルファイルとビューコントローラファイルを示しています。モデルファイルはクラスです。 そのコードは機能します。ここで

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

問題:私は今の代わりに構造体を使用するモデルファイルのコードを変更したい。ここ

はモデルファイルでありますこの非常に簡単なプログラムとしてのクラスは、クラスのすべての機能を必要としません。しかし、すぐに構造体のクラスを変更します。プログラムはまだ実行されますが、デリゲート変数がnilに設定されていて別の値を取得しないため、ラベルは更新されません。

質問:何が欠けていますか?迅速なドキュメントは、可能であればstructを使用することを奨励しています。そして、私はそのコードで、クラスを構造体に変換する際の問題であるとは見ていません。

+0

クラスを構造体に変更するときに、 'mutating func incrementCounter()'を追加してみてください。私はデフォルトでは、 'value'型のプロパティはそのインスタンスメソッド内から変更できないと思います。 – Simon

+0

@サイモン。これは[func incrementCounter]が構造体のメソッドであった場合に機能します。 –

答えて

2

構造体は不変であり、クラスのように参照渡しされず、値渡しされます。これは、そのときのことを意味します。

var model1 = model 

modelのコピーを作成しています。

model1を変更すると、modelに変更が反映されないため、incrementCounterのすべてがビューコントローラに反映されません。

incrementCounterをviewControllerに適用するには、viewControllerインスタンスのモデルを使用する必要があります。

modelプロパティを共有し、このモデルが更新されたときにラベル値を変更することを意図している場合は、構造体が最適な選択ではありません。

+0

@Guiseppe Lanza - そうです。しかし、プログラムを実行すると、VCのボタンを押すと、モデル内でカウンタが増分され、model.messageが設定され、didSetが実行されますが、デリゲートの値がnilであるため、命令は中止され、何もVCに返されません。 –

+0

私はモデルとモデル1はお互いを知らないと述べた。それらは2つの異なるメモリ割り当てです。一方を変更しても他方には影響しません。つまり、model1の代理変数varを変更すると、これはモデルでは設定されず、モデル内の変数を変更すると、model1にあるものは変更されません。 –

関連する問題