Swift:Cocoa绑定到计算属性的值不起作用

时间:2016-03-09 13:16:00

标签: swift cocoa cocoa-bindings

我正在学习KVC和绑定。目前,我正在尝试将NSTextField绑定到计算属性colorWallStr。我已将滑块的值绑定到相应的颜色变量,并将标签的值绑定到计算属性。

但是,当我移动幻灯片时,标签的内容不会改变。

// Inside MainWindowController
dynamic var colorRed: CGFloat = 1.0
dynamic var colorGreen: CGFloat = 1.0
dynamic var colorBlue: CGFloat = 0.0

dynamic var colorWallStr: String {
    get {
        return "R: \(colorRed) G: \(colorGreen) B: \(colorBlue)"
    }
}

enter image description here enter image description here

将标签直接粘贴到颜色变量时工作正常。

enter image description here

谢谢@ vadian的回答。现在我可以使用属性didSet更新标签以触发更新标签方法(见下文)。

dynamic var colorBlue: CGFloat = 0.0 {
    didSet {
        updateLabel()
    }
}

func updateLabel() {
    colorWall = "R: \(colorRed) G: \(colorGreen) B: \(colorBlue)"
}

如果字符串插值中使用的属性不更新封闭的计算属性,那么为什么以下代码片段不起作用?

dynamic var colorWall: String {
    get {
        let red = colorRed
        let green = colorGreen
        let blue = colorBlue
        return "R: \(red) G: \(green) B: \(blue)"
    }
}

4 个答案:

答案 0 :(得分:5)

Key-Value Observering API允许您通过注册依赖键来处理这种情况。以下是文档介绍主题的方法:

  

在许多情况下,一个属性的值取决于另一个对象中的一个或多个其他属性的值。如果一个属性的值发生更改,则还应标记派生属性的值以进行更改。

在这种情况下,colorWallString 的值取决于三个颜色变量的值,因此您需要做的就是实现一个明确的类方法:

// It's crucial that you get the signature of this method correct, 
// otherwise it'll just be ignored.
class func keyPathsForValuesAffectingColorWallStr() -> Set<NSObject> {
    return Set<NSObject>(arrayLiteral: "colorRed", "colorBlue", "colorGreen")
}

如代码段中所述,用于标记依赖键的方法格式至关重要;你可以(而且应该)阅读relevant documentation here

答案 1 :(得分:1)

字符串插值中使用的属性不会更新封闭的计算属性。

你可以这样做

dynamic var colorRed: CGFloat = 1.0  { didSet { updateLabel() } }
dynamic var colorGreen: CGFloat = 1.0  { didSet { updateLabel() } }
dynamic var colorBlue: CGFloat = 0.0  { didSet { updateLabel() } }

dynamic var colorWallStr = ""

func updateLabel()
{
  colorWallStr = String(format:"R: %.2f G: %.2f  B: %.2f ", colorRed, colorGreen, colorBlue)
}

答案 2 :(得分:1)

对于Xcode 9.0,Swift 4:

class SampleViewController: NSViewController {

  @objc dynamic var colorRed: CGFloat = 1.0
  @objc dynamic var colorGreen: CGFloat = 1.0
  @objc dynamic var colorBlue: CGFloat = 0.0

  @objc dynamic var colorWallStr: String {
    get {
      return "R: \(colorRed) G: \(colorGreen) B: \(colorBlue)"
    }
  }

  override class func keyPathsForValuesAffectingValue(forKey key: String) -> Set<String> {
    switch key {
    case "colorWallStr" :
      return Set(["colorRed", "colorGreen", "colorBlue"])
    default :
      return super.keyPathsForValuesAffectingValue(forKey: key)
    }
  }

}

小提示:

  • 在这种情况下,使用NSViewController代替NSWindowController

更多信息:

答案 3 :(得分:0)

“在某些情况下,价值可能取决于另一个。例如,如果你有一个Person类,其计算属性fullName依赖于属性firstName和lastName,那么当firstName或lastName更改时,是否可以通知fullName的观察者,这不是很好吗? KVO的设计师也这么认为,这也是他们实现定义依赖键的约定的原因。 要定义键的依赖项,必须实现一个特殊命名的类方法,该方法返回一组键路径。在上面的示例中,您将实现keyPathsForValuesAffectingFullName():

摘录自:亚伦的希勒加斯。 “OS X的可可编程:大书呆子牧场指南,5 / e(大书呆子牧场指南)。”iBooks。