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:
NSTableColumndoes not have acontinuousproperty. There are classes that do (e.g.NSControlandNSCell), butNSTableColumndoesn'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
.continuouslyUpdatesValuebinding 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,
NSTableColumncan't really be a responder, at least in the traditional sense. And this option has no effect on bindings from anNSTableColumn'swidth.Confusingly, this option also has no effect on bindings from
NSSlider. Instead, ifNSSlider'scontinuousproperty isfalse, it will always only update the binding on mouse up, even if the.continuouslyUpdatesValueoption is set on the binding. Conversely, ifNSSlider'scontinuousproperty istrue, it will always update the binding's value continuously, even if the.continuouslyUpdatesValueoption is set to false on the binding.Some digging with the debugger explains this behavior.
NSSlideralways updates its bindings value as a side effect of sending its action to its target (regardless of the.continuouslyUpdatesValueoption). This explains why itscontinuousproperty solely determines its behavior.On the other hand, while
NSTableColumnupdates itswidthproperty and thus emits KVO notifications continuously as its width is changed, it only updates itswidthbinding as a side effect of posting thecolumnDidResizeNotificationthat it posts on width changes. This notification is only ever posted at the end of a resize, not during a resize. Thus,NSTableColumnonly ever updates its binding at the end of a resize.