2016-03-09 22 views
2

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

回答

5

键 - 值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

+0

我只是试过你的片段,但我还没有工作。感谢您的额外资源。 –

+0

好吧,不知道是什么问题。在发布之前,我将它设置在一个小应用程序中,并且工作正常。我的代码与您问题中第一个代码块中的代码以及我的答案中的代码块完全相同。你应该看看''keyPathsForValues..''方法是通过在''return''语句中放置一个断点来调用的。当你的应用程序启动时,如果它已被正确定义,程序应暂停执行。 –

+0

我刚刚重建了应用程序,它现在正在工作! –

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

谢谢@vadian,这个工程就像一个魅力。我没有这样做,因为在每个变量都很丑陋之后,我经常放置'{didSet {functionName()}}'。 = P –

+0

还有一个问题,请在问题结尾处查看我的更新问题。 –

+1

我必须承认,保罗的解决方案要好得多。我不知道'keyPathsForValuesAffecting ()'在Swift中可用,我经常在ObjectiveC – vadian

0

“在一些情况下的值可以依赖于另一个。例如,如果你有一个计算的属性全名是依赖于属性firstName和lastName一个Person类,岂不是很好,如果全名观察员可以通知当任的firstName或lastName的变化? KVO的设计师也这样认为,这就是为什么他们实现了定义相关密钥的惯例。 要定义一个键的依赖关系,你必须实现一个特殊的命名类方法,它返回一组关键路径。在上面的例子中,你将实现keyPathsForValuesAffectingFullName():

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

0

有关的Xcode 9.0,雨燕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) 
    } 
    } 

} 

小tips:

  • 使用NSViewController,而不是NSWindowController,在这种情况下。

更多信息: