2
votes

I'm working on an existing Swift/Objective-C project on the Mac and I'm creating some UI in code. I enable a button based on the selection in a NSTableView that I manage without using NSArrayController (for reasons).

I have a property selectionIndexes on MyController:

@objc var selectionIndexes : IndexSet = IndexSet()

I'm not sure whether the @objc is necessary to make it visible to the Cocoa Bindings system.

I connect the button's enabled binding using:

newButton.bind(NSBindingName.enabled, to: MyController.sharedInstance,
     withKeyPath: "selectionIndexes", 
     options: [NSBindingOption.valueTransformer : MyTransformer()])

This works fine, the transformer is called with the correct property and enabled is set correcty, but changes to the selection do not trigger the binding, so the button remains disabled.

I had to explicitly tell the system that I'm changing the value, e.g.

self.willChangeValue(for: \.selectionIndexes )
self.selectionIndexes = proposedSelectionIndexes
self.didChangeValue(for: \.selectionIndexes)

This seems pretty lame. Is there a better way of doing this?

1

1 Answers

4
votes

@objc is necessary to expose the property to the Objective-C runtime.

To make the property key-value observing compliant you have to add the dynamic keyword

@objc dynamic var selectionIndexes = IndexSet()

and delete the ...ChangeValue(for lines