2017-06-21 47 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(消息:消息)”不执行,因为委托值是零。我想问题是我不正确地声明/初始化委托属性。 你会建议如何解决这个问题?任何关于详细和清晰地涵盖这些主题的书的想法? –