Auto-sort table column contents bound to NSArrayController - objective-c

So, this my case :
I've got an NSMutableArray (of NSMutableDictionary instances) bound to an NSArrayController. Each element's name value is, in turn, bound to the value of the first table column.
The thing is :
How should I make it auto-sort the elements in that specific table column (of my NSTableView) ?

Is the column sortable through user action? For the table column's Value binding, you can enable the Creates Sort Descriptor option. That's enabled by default, usually. You should also set the Sort Key and Selector in the attributes inspector.
If you're trying to make the table sorted when the window is first loaded, you should construct an array of NSSortDescriptors and pass that to the array controller's -setSortDescriptors: method. A good time to do this is in an override of -windowDidLoad in the window controller or during -awakeFromNib.

Related

Creating an array item with a property that's dependent on an aggregate function on the array itself

Suppose I have an NSArrayController containing a number of 'blob' objects. These objects are displayed in a view-based NSTableView via bindings.
Now suppose that each 'blob' object contains a property called amount. For one of the NSViews in each row of the table I'd like to display amount / max_amount_in_array.
In other words, I somehow need to bind my cell to the NSArrayController's arrangedObjects.#max.amount and to the NSTableViewCell's objectValue.amount at the same time and perform my calculation.
Is there a way to handle this nicely using bindings?
Currently the only idea I have to is to have a ratio property in 'blob' and recalculate it myself every time that an object is added to the array. That's quite possible, but it just seems like there should be a more bindings-like way to solve the problem.
I've now done this like so:
[libraryCell.myView bind:#"amount"
toObject:libraryCell
withKeyPath:#"objectValue.amount"
options:nil];
[libraryCell.myView bind:#"max"
toObject:_librariesController
withKeyPath:#"arrangedObjects.#max.amount"
options:nil];
There are thus two properties in myView (amount and max) and when either of them change I do the calculation and update the display accordingly.

How to show calculated values in NSTableView?

I have an NSTableView that binds via an NSArrayController to an NSMutableArray of NSString's.
There's also a TextView in the same window. What I want to do is display a number of occurrences of each NSString in the NSTableView.
I've thought of a way to do this, but that doesn't look elegant way of doing this:
Inherit from NSString and define new method that performs a search in predefined object (NSTextView) and returns the number of occurrences.
I'm guessing there must be a more natural way of achieving the same result?
EDIT:
Sorry, should have clarified. NSSMutableArray is an array of NSObjects that have an NSString property. I suppose I could define an extra method (findAllOccurencesOfString:inString:) which would return a number. But the question is how do I bind to this function and in that binding how to I pass a var (pointer to textField)??
You'll need to have a wordCount (read only) property on whatever objects are in your table data source, this will have to call your new method internally using the object's own string value, as you can't pass parameters in bindings (unless they've changed, I haven't used bindings for a while as I've been concentrating on iOS). Then bind to this property for the column in the table. Presumably you don't need to pass the pointer to the textfield as there is only one?

Text field bound to array controller does not change the value in the array

I have a text field that I am using to show a "total cost" computed from several other text fields. When I get controlDidEndEditing:, I calculate this total cost and put it into the Total Cost field using setDoubleValue:. I have the value of the Total Cost field bound to an array controller, and if I change the field's value manually, then it is saved into the controller's array. If I do it programmatically, though, then the field's display will change but the array and the value displayed in my table does not change.
What is the reason?
If you have a bound control, like a textField, changing it's state using a method like setStringValue: will not trigger the bindings mechanism to push the change out to the binding target. This is simply part of the design of bindings. If you want to effectively change the value of the textField programmatically, you need to change it in your model object using the setter for the key you have it bound to, or using setValue:forKey. So if you have nameTextField bound to person.name, you need to call [person setName:newName] or [person setValue:newName forKey:#"name"].

Binding columns in an NSTableView

I have two classes: GHTable and GHColumn. A GHTable object has an NSMutableArray with GHColumn objects. Each GHColumn has a name property (NSString).
I have made an UML diagram to make this more clear. Note that I am not using Core Data:
I want to bind the columns property of the GHTable object to the columns of an NSTableView. I want to bind the titles of the columns of the NSTableView to the name property of the corresponding GHColumn.
My question: is there a way to do this through Cocoa Bindings, and if so: how? Or do I need to manually implement the data source for the NSTableView?
You will need to use an NSArrayController. Bind its Content Array binding to the mutable array on your GHTable object.
In the NSTableView, bind Content to the NSArrayController's arrangedObjects contoller key.
In the NSTableView's column, bind Value to the NSArrayController's arrangedObjects controller key with the model key path name.
If the inspector window shows "Scroll View Bindings" as its title when you click the table view, click it again on the content area and it should change to "Table View Bindings".
Click again on the table's column to select it and the title should change to "Table Column Bindings".

Inserting image into NSTableView using bindings

I've an NSTableView bound to an NSArrayController with two columns. One column is bound to the arranged objects of the array controller and displays a string.
I'd like to display an image in the other column, but I just can't make it work. I've dragged an NSImageCell to the column and set the image by hand but it won't show up at runtime. I've double checked and the image is in my resources directory.
Am I missing something? What else should I do to make that image appear?
So you want to have the same image appear for each row? Is that why you're setting it "by hand"? For that, you can mix NSTableViewDataSource methods with bindings. The idea is your string column will be bound as usual, but your image column isn't bound. It has its identifier set (like "imageColumn"). You then use numberOfRowsInTableView: and tableView:objectValueForTableColumn:row: to provide the array controller's object count (so it has the right number of rows) and simply always return your static image when it asks for the value for the right column (checking the id for your "imageColumn"), returning nil otherwise.
If the image is not static (that is, you want to use it as an indicator of some kind) you can use the above method (return some image based some value) OR bindings. To use Bindings, you might add a property to whatever class your array controller is holding, like "status" (a number). You'll then use a custom NSValueTransformer that transforms the status number into a corresponding image. Your column will be bound to the array controller's arrangedObjects.status, using the value transformer (see NSValueTransformer for instructions for use - you have to register it, then use its name). The result is an image in your column that corresponds to a certain status.