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

Swift: Cocoa binding value to a computed property does not work

我正在学习 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)"
    }
}

当我直接将标签绑定到颜色变量时,它工作正常。

感谢@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)"
    }
}

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

你可以这样做

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

键值观察 API 允许您注册 依赖键 来处理这种情况。以下是文档介绍主题的方式:

There are many situations in which the value of one property depends on that of one or more other attributes in another object. If the value of one attribute changes, then the value of the derived property should also be flagged for change.

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

// 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.

“在某些情况下,一个值可能依赖于另一个值。例如,如果您有一个 Person class,其计算的 属性 fullName 依赖于属性 firstName 和 lastName,如果可以在 firstName 或 lastName 时通知 fullName 的观察者,那岂不是很好变化? KVO 的设计者也这么认为,这就是为什么他们实施了定义依赖键的约定。 要定义键的依赖关系,您必须实现一个特别命名的 class 方法,该方法 returns 一组键路径。在上面的示例中,您将实现 keyPathsForValuesAffectingFullName():

摘自:Hillegass, Aaron。 “Cocoa OS X 编程:大书呆子牧场指南,5/e(大书呆子牧场指南)。”电子书。

对于 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

更多信息: