In a macOS Cocoa Application if I have two NSSlider objects, I can set the following binding programmatically:
@IBOutlet weak var firstSlider: NSSlider!
@IBOutlet weak var secondSlider: NSSlider!
func applicationDidFinishLaunching(_ aNotification: Notification) {
// Insert code here to initialize your application
self.firstSlider.bind(NSBindingName.init(rawValue: "value"), to: self.secondSlider, withKeyPath: "value", options: [NSBindingOption.continuouslyUpdatesValue : true])
}
This works, but not continuously updating, unless I set the Continuous checkbox in the inspector in interface builder for the sliders. My problem is that I would like to set the binding between other properties that do not expose a continuous setting by themselves, specifically two NSTableColumn instances. Is it possible to bind continuously by setting an option in the binding code?
The short answer to your question is no, this is not possible. You should just use your own KVO code as you've already discovered.
Longer answer follows:
Fundamentally, the issue is two fold: NSTableColumn
does not have a continuous
property. There are classes that do (e.g. NSControl
and NSCell
), but NSTableColumn
doesn't inherit from these. Technically, this property is meant to determine whether a control sends its action method to its target continuously, rather than specifically being about bindings, though it does also affect binding behavior.
The .continuouslyUpdatesValue
binding option means something slightly different. It is used to determine whether bound value is updated continuously during user interaction or only when the UI element resigns its responder status (ie. user interaction stops). This is mostly useful for text field/view bindings.
Unfortunately, NSTableColumn
can't really be a responder, at least in the traditional sense. And this option has no effect on bindings from an NSTableColumn
's width
.
Confusingly, this option also has no effect on bindings from NSSlider
. Instead, if NSSlider
's continuous
property is false
, it will always only update the binding on mouse up, even if the .continuouslyUpdatesValue
option is set on the binding. Conversely, if NSSlider
's continuous
property is true
, it will always update the binding's value continuously, even if the .continuouslyUpdatesValue
option is set to false on the binding.
Some digging with the debugger explains this behavior. NSSlider
always updates its bindings value as a side effect of sending its action to its target (regardless of the .continuouslyUpdatesValue
option). This explains why its continuous
property solely determines its behavior.
On the other hand, while NSTableColumn
updates its width
property and thus emits KVO notifications continuously as its width is changed, it only updates its width
binding as a side effect of posting the columnDidResizeNotification
that it posts on width changes. This notification is only ever posted at the end of a resize, not during a resize. Thus, NSTableColumn
only ever updates its binding at the end of a resize.