Solution for Ch 22 Challenge: Convert RGBWell to Use Bindings

#1

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

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

#3

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()
    }
}
#4

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

}

}