Solution for Ch 22 Challenge: Convert RGBWell to Use Bindings

The Dependent Keys section in book is very helpful for the solution.

The IBOutlets are defined just for purpose of defining bindings in code.

//  MainWindowController.swift

import Cocoa

class MainWindowController: NSWindowController {
  override var windowNibName: String? {
    return "MainWindowController"
  }
  
  @IBOutlet weak var rSlider: NSSlider!
  @IBOutlet weak var gSlider: NSSlider!
  @IBOutlet weak var bSlider: NSSlider!
  @IBOutlet weak var colorWell: NSColorWell!
  
  dynamic var r = 0.0
  dynamic var g = 0.0
  dynamic var b = 0.0
  let a = 1.0
  
  dynamic var newColor: NSColor {
    return NSColor(calibratedRed: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(a))
  }
  
  class func keyPathsForValuesAffectingNewColor() -> Set<String> {
    return ["r", "g", "b"]
  }

  override func windowDidLoad() {
    super.windowDidLoad()
    
    rSlider.bind(NSValueBinding, to: self, withKeyPath: "r", options: nil)
    gSlider.bind(NSValueBinding, to: self, withKeyPath: "g", options: nil)
    bSlider.bind(NSValueBinding, to: self, withKeyPath: "b", options: nil)
    colorWell.bind(NSValueBinding, to: self, withKeyPath: "newColor", options: nil)
  }
}

I used a different approach , the code in MainWindowController reduced to

import Cocoa

class MainWindowController: NSWindowController {
@IBOutlet weak var colorWell: NSColorWell!
private var privateRed = 0.0
private var privateGreen = 0.0
private var privateBlue = 0.0
dynamic var red: Double {
set {
privateRed = newValue
colorWell.color = colorWellValue
}
get {
return privateRed
}
}
dynamic var green: Double {
set {
privateGreen = newValue
colorWell.color = colorWellValue
}
get {
return privateGreen
}
}
dynamic var blue: Double {
set {
privateBlue = newValue
colorWell.color = colorWellValue
}
get {
return privateBlue
}
}
var alpha = 1.0
dynamic var colorWellValue: NSColor {
get {
return NSColor(calibratedRed: CGFloat(red), green: CGFloat(green), blue: CGFloat(blue), alpha: CGFloat(alpha))
}
}

override var windowNibName: String? {
    return "MainWindowController"
}
override func windowDidLoad() {
    super.windowDidLoad()
}

}

and using Interface Builder, for each slider I went to the bindings inspector and set the value binding to
Files Owner and modal key path to the appropriate dynamic variable red, green, blue

Ok here is my solution based on hkray’s solution

import Cocoa

class MainWindowController: NSWindowController {
    dynamic var r = 0.0
    dynamic var g = 0.0
    dynamic var b = 0.0
    
    
    var a = 1.0
    dynamic var color:NSColor {
        return NSColor(red: CGFloat(r), green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(a))
    }
    class func keyPathsForValuesAffectingColor() -> Set<String> {
        return ["r", "g", "b"]
    }

    
    override var windowNibName: String? {
        return "MainWindowController"
    }
    
    
    
    override func windowDidLoad() {
        super.windowDidLoad()
    }
}

My solution based on asurin and updated to Swift 5

import Cocoa

class MainWindowController: NSWindowController

{

@objc private dynamic var r: Double = 0.5

@objc private dynamic var g: Double = 0.5

@objc private dynamic var b: Double = 0.5

@objc private let a: Double = 1.0

@objc private dynamic var cor : NSColor

{

return NSColor(calibratedRed: CGFloat®, green: CGFloat(g), blue: CGFloat(b), alpha: CGFloat(a))

}

@objc class func keyPathsForValuesAffectingCor() -> Set

{

return [“r”, “g”, “b”]

}

override var windowNibName: String?

{

return “MainWindowController”

}

override func windowDidLoad()

{

print(“windowDidLoad()”)

super .windowDidLoad()

}

}