参考资产上的swift属性观察者

时间:2017-06-21 19:21:15

标签: swift properties

如何获取引用属性以触发属性观察者?

为了演示我的问题,我用一个按钮和一个标签编写了一个简单的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工作,我会很感激,因为我计划在真实程序中使用它。

2 个答案:

答案 0 :(得分: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 = self设置为viewDidLoad

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

}

答案 1 :(得分:1)

如果有人对此感兴趣,请使用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()
    }    
}