I've got a table one column of which uses an NSPopUpButtonCell. Try as I might, I can't seem to figure out the way to properly bind everything the way I want it. Here's what I'm trying to do:
I have an NSArrayController plucking items from a managed object context, called 'Field Values'. This is to be used to populate the popup menu for each item (i.e. the list of available choices). I can bind this by selecting the cell in IB and binding its content/objects/values to 'Field Values'.arrangedObjects and 'Field Values'.arrangedObjects.name as appropriate (to get the represented object and the visible title).
I then want to bind the column in such a way that the selected value in each row comes from an array in my controller class, again made visible (and only edited through) another NSArrayController.
So far I've managed to set it up so that every popup menu contains the list of available fields, and that the default value is selected in each of them. Actually selecting an item has no effect, however— it just snaps back to its initial value. I've also managed to find some other variations on this, such as the menu being populated with the selected values, or containing the name of all available values, and the selection containing the -description of the 'none' value I added.
I'm sure I'm missing something fairly simple, but I'm not sure what it is. Presumably there's some subtlety I've missed in how to bind this sort of data (i.e. the Content vs. Content Object vs. Content Value things), but I'm damned if I can see it right now.
Many thanks in advance :o)
I've got a similar set up with a table view, although the data source isn't Core Data based, but I saw one thing you might double check that could be a subtle difference. In my setup for the table column, I have the table column itself bound via content, contentValues, and selectedObject. However, it looks like it's also possible to do the bindings on the actual NSPopUpButtonCell instead. Perhaps it works when the bindings are on the table column, but not when they're on the actual cell? Anyway, there's one thing that might be worth looking into.
Never bind to scroll view, table view or cell.
However, ever bind to table columns.
Watch the title of the Inspector window to be certain of what you're binding.
Related
I have a main NSArrayController bound to an NSTableView with each row containing an instance of MyObject. MyObject has about 30 properties, but the NSTableView only has 5 columns (to show the most important properties). When a row (or more) is selected I have another NSTableView (a detail view) which shows all the properties, one per row. The detail table has two columns, one for the property name and one for the property value.
I have this working right now but my detail NSTableView uses a data source rather than bindings. This works fine as long as I notify my detail controller (which manages the data source) of a change in the main selection so that it can reload the detail table.
While it is easy to detect a change in selection, it is harder to detect a change in one of the properties of a selected object. I see elsewhere on StackOverflow, that one way to do this is to have a dummy property and use keyPathsForValuesAffectingValueForKey. Does this work well performance-wise?
Is there some other/better way to build my detail NSTableView/NSArrayController so that each row represents one property of the selected objects on the main NSTableView/NSArrayController? I'd like to use bindings if possible.
im a osx-dev noob that is trying to build an application with three table views that will show the content of a core data store entity. But each table view is filtered on the attribute "status" of the entity.
the problem occurs when i also want to show the selected entity in textfields. I'm using three different array controllers with different fetch predicates. But in a textfield i can only bind the value to one array controller.
should i ditch the bindings and do it all programaticly or is there a simple solution to this? :)
here is an screenshot so you can grasp my app description.
Keep bindings to populate the text fields if it satisfies what you want to do with this GUI. I'd add an NSObjectController to control the one entity those fields represent. If you want the user's changes to those fields persisted, bindings are still awesome.
But I think with three tables that might control what's displayed in the text fields, you're going to need to have some sort of non-binding glue code that determines which of the tables wins. You can probably do everything you want by implementing some of the NSTableViewDelegate protocol.
If the text fields should display the last entity that the user clicked in any of the tables, simply have each table call the same tableViewSelectionDidChange delegate function. All three tables could have the same delegate. You can then call setContent on the NSObjectController from that function.
You could also use similar glue code to prevent more than one selection in any of the three tables, by having the same delegate function deselect everything in the other tables either through the view or the controller. But that's up to you and needs consideration of whether you want multiple selection, etc.
There are similar questions to this already, but I haven't found any of them to work for me. All I want to do is re-sort the table view based on clicking the column header. And I don't want to do this programmatically because I don't think I have to. Anyways...
I have a NSTableView binded to an NSArrayController that is binded to my managedObjectContext.
For a specific NSTableColumn, I have the value binded to the Array Controller with the model key path "amount" which is an NSNumber.
I see in the attributes for this NSTableColumn, there is a "Sort Key" and a "Selector". I set the sort key to "value.amount" (not sure why, but I saw this elsewhere) and the selector defaults to "compare:" which seems fine.
Then for the NSArrayController, I see a binding called "Sort Descriptors" which I bind to "Shared User Defaults Controller". The "Controller Key" defaults to "value" (I assume this is why I used value before), and I set the "Model Key Path" to "amount.
This sounds reasonable, I suppose. But (1) it doesn't work and (2) what about when I want to sort based on two different columns? Also, (3) how do I set the default way to sort?
UPDATE:
OK, so I have the array controller binded to the managed object context. I have the table content binded to the array controller arranged objects, and selection indexes to the array controller selectionIndexes. I have a table column value binded to array controller arrange objects and the associated key. the sort key for that column is the same key with a compare: selector.
The table is not reordering when I click the headers though. Am I supposed to bind the sort descriptors of the table?
If possible, can you send me your example?
Thanks for the help,
Chet
First thing you should know is both the NSTableView and the NSArrayController can sort your items. You’re trying to set a mix of both right now, and there’s no point in that. For simple uses, just rely on the tableView.
So, don’t bind anything in the NSArrayController. For the NSTableColumns, don’t use “value.amount”, just use “amount”. “compare:” is fine for the selector.
I just created a tiny project (no code) to demonstrate this and it worked great with sorting.
I'm trying to achieve something similar to the Apple Master-Detail pop-up cell example but the bindings don't seem to be working for me.
My app allows users to build up a stageplay; so I have a table view of acts. Each act can have a list of lines so the acts table view drives a second table view of lines (so selecting act one updates the lines table view with the lines of that act).
This setup seems to be working fine.
Each line is of course spoken by a character, so my document object has a list of characters as well as a list of acts. What I want is a pop-up cell in my lines table with values taken from the characters array.
So I followed the steps in that Apple tutorial but it doesn't work...
If I bind the content of the table view column to the CharactersController.arrangedObjects and the selectedObject to LinesController.arrangedObjects.character then the binding works (when I select a value from the pop-up it updates the underlying line object with the new character), but the list shows <Character ...> entries
If I then bind the column's contentValues to CharactersController.arrangedObjects.name then I get the following debug error when I run the app:
2011-03-16 11:28:49.783 ScriptPreparer[5176:903] Cocoa Bindings:
Error setting value <Character: 0x100144f60> of object
<NSPopUpButtonCell: 0x100153ff0> through binding selectedObject
If I remove the selectedObject binding then I still get the <Character...> output in the list.
It seems like the contentValues binding is the broken one. What am I doing wrong?
Here are my bindings:
I discovered what the problem was - I had bindings set on the NSTableView as well as the Table column and the NSPopupButtonCell which was causing strange things to happen.
My conclusion is now that any table bindings not on the table column are WRONG
I have a class named as transaction in which one attribute is transactionDate which is of type NSDate.
I am using NSArrayController to display a list of transactions in a table view.
My requirement is-
I want to show date in first row in a
text field labeled as "From" and date
in last row in a text field labeled as
"To".
My questions is-
Can I achieve this via binding in IB?
If yes then how?
Thanks,
Miraaj
Yes, you can do this (or something like it), see the #min and #max array operators.
Here's how to do a very simple version of this:
Open Interface Builder - create a new application
Add an NSArrayController, set it to automatically prepare content.
Add a Table, label the two columns "name" and "age"
Add a Button (labelled "+") and two Labels (change name to maxval, minval)
Wire up the NSArrayController bindings as follows:
Here's the application running (just in interface builder "simulate" mode). To use it, click + then click on the top row of the table and put a name in the first column and an age in the second. Then repeat for a few more people.
This all looks a bit cryptic, but it is sufficient. I added the labels "Max Age" and "Min Age" for clarity in my version.
Unfortunately this is not something Bindings is particularly good at. You could achieve it but it would be very hacky.
The NSTableViewDataSource protocol is still a perfectly relevant and valid way to provide data to a table. In cases like these (where you're not just presenting a straight-vanilla set of uniform data to a table) the data source protocol is the only sane way to solve the problem. This way you're in complete control of what the table displays.
The only "hard" part is that, if you're using Core Data, your data source class will need to observe the Managed Object Context for changes and reload the data (either -reloadData to refresh the whole table or use -reloadDataForRowIndexes:columnIndexes: to cherry pick the rows you want to refresh).