NSPopupButton not working in an NSTableview - objective-c

I have a program using Core Data, with the columns of an NSTableView bound through an NSArrayController. This is working with out an issue, table columns populate without issue. I am expanding the table to include an NSPopupButton - however something odd happens when the button is added. Just dragging the button in to the column, then running the program without connections or binding to the Popup, all the other columns do not populate correctly - they just show the default placeholder text.
Thoughts?
I can get the NSPopupButton to populate, but still the other columns only show the default text. If I remove the NSPopupButton everything works fine.
Why would the other columns have issues? I tried added a CheckBox and had the same issue. I've searched around the net and SO, but have not found an answer.
I would appreciate any thoughts/suggestions.
Thank you in advance.
[EDIT]----
The Table is view-based and NSTableCellView.
arrayController:
Bound to Entity Name
Parameters, bound to Main Controller; key path:managedObjectContext
TableView:
Columns:
Value: Bound to arrayController, key path: name, age, etc...
NSPopupButton:
Value: Bound to Main Controller, Path: catArrayController.arrangedObjects.name
Main Controller:
IBOutlet: catArrayController
Bound to catArrayController in IB

With a view-based table view, you are intended to bind the table view's Content binding to the array controller. You do not bind the columns' Value binding. From Table View Programming Guide for Mac: Populating a Table View Using Cocoa Bindings:
Note: In an NSView-based table, you bind the table view’s content to the array controller’s arrangedObjects. This differs from the technique you use if you’re working with an NSCell-based table.
That binding causes each cell view to have its objectValue property set to the object corresponding to the row, if it has such a property. Note that the cell views don't get a column-specific value. All of the cells of a row get the same value.
Since your cell views are NSTableCellViews, they have an objectValue property. Then, the subviews of the cell view should have their Value binding bound to the cell view with a key path running through objectValue to the specific property (name, age, etc.).
In the old NSCell-based table views, you would typically not bind the Content (or Selection Indexes or Sort Descriptors) bindings of the table view itself at design time. You would bind the table columns as you have done. At run time, the table view would automatically establish bindings for its own Content, Selection Indexes, and Sort Descriptors based on the bindings of its columns. I suspect some version of this behavior was happening in your app which was allowing things to kind of work. However, I suspect that adding the new column broke that system. It was a fluke that it was working for the view-based table view in the first place, so was inherently fragile.

Related

ArrayController's CoreData selection binding not refreshed across multiple NIB files

I've a hard time getting my Cocoa application to work as expected. It consists of a toolbar in the main.nib and a custom view in a details.nib file. Now I want the user to select an entry in a NSPopupButton in the toolbar and the content of the custom view should be changed accordingly.
To achive this I've added an ArrayController to my main.nib, showing the following configuration:
Furthermore the Managed Object Context is bound to the Model Key Path delegate.managedObjectContext (it is no document based application).
With this configuration the NSPopupButton works just fine and if I add a Label to the toolbar (also in the main.nib) and bind it's value to the selection (Controller Key), name (Key Value Path) the content is refreshed whenever I change the selection.
The Bindings of the NSPopupButton look like shown in the following screenshot:
So in my details.nib I tried the following to achieve the same effect. I've added an ArrayController, whichs Managed Object Context is also bound to the Model Key Path delegate.managedObjectContext. Also the configuration is exactly the same as shown in the above pictures. I've then added a label and bound it's value to the selection (Controller Key), name (Key Value Path) of this ArrayController.
The problem is that the Label only displays the the initial selection after the application did launched correctly. Afterwards, when I change the selection of my NSPopupButton, the label does not change accordingly.
What are my options to get the ArrayController working accross multiple NIB files?
BTW: I've tried to follow this blog post to get it working but it seems I'm missing something here.
Update:
If I replace the Label in the details.nib by a NSTextField and change the text of it, the changes are reflected in the related NSPopupButton entry. So I guess I made something right, but the main problem remains: I can only edit the entry which was loaded during application startup. Switching to another NSPopupButton entry does not change the text in the NSTextField.
Update 2:
I've created a small sample project with exactly the same configuration and uploaded it on GitHub. So feel free to check it out or create a pull request with a solution approach.
It seems you're missing the fact that, when you create the second array controller on the Details.xib it has no relation to the array controller on the MainMenu.xib. They are two separate instances.
When you change the selection on the PopUp the only array controller affected is the one on MainMenu.xib.
You have several options here:
When you create your DetailViewController pass a reference to the array controller on the Controller and bind to that (don't create a new one on the details.xib)
Just use simple KVO to observe the selection on Controller, and programatically change your label value.
Just use simple KVO to observe the selection on Controller and update the array controller on the DetailsViewController to keep them in sync.
your solution here...
As long as you understand what's going on I'm sure you'll find the best solution to your original problem.

NSArrayController selection not updating with NSTableView binding

This has been befuddling me for hours...
I have an object (CuesDoc) with a property (NSMutableArray *cuesArray) and some other properties. The cues array holds multiple Cue objects. There is a property called (CuesDoc*) currentCuesDoc in my AppDelegate.
In IB, I have an NSArrayController, which is bound to the AppDelegate.currentCuesDoc.cuesArray.
I have a view-based NSTableView which is bound to the NSArrayController and can add/remove/edit values in the table and cuesArray. So far so good.
I have detail fields below that, which are bound to NSArrayController.selection, with the model key path set to each property.
When the view first appears, the detail fields populate with the contents of the first item in the table view, however when I select other rows, the detail fields do not update to reflect the current selection.
I added an observer to selectionIndexes and selection for the NSArrayController, and when the view appears, I get called for the observeValueForKeyPath: method once, but not after changing selections.
For view-based NSTableViews, you must bind the tableView's selection indexes to the array controller key of selectionIndexes to keep the view's selection in sync with the controller's selection. Selection bindings are separate from content bindings. The older, cell-based NSTableView APIs did not require this step.

Cocoa Bindings "Selection" not changing when table rows clicked

Hello there: I have in essence a master-detail application with one master view-based NSTable view and two detail views. My master NSTable loads and displays data from a Managed Object Context correctly. One of my detail views should load the image of the object in selected table row. But here is my problem that no one else on the Internet seems to have:
My "selection" object isn't changing. I did bind the the value of image view on my detail view to the Array Controller, and controller key is: "selection", model key is "image". The image view only loads the first object's image in the table, and if I click/select on other rows, the image isn't changing. So it seems like "selection" object is always the first object. Since this is all done in Interface Builder, I don't have any code to show, sorry.
Does anyone know what is going on? Why is the "selection" object always the first in the table? Thank you!
You need to bind the NSTableView’s selection to the NSArrayController’s, like so:

NSArrayController changes doesn't propagate to binded NSUserDefaults

I have a master-detail GUI layout:
NSTableView with content bound to an NSArrayController.
The NSArrayController data is bound to NSUserDefaults rows.
An NSTextField with value bound to the NSArrayController's selection property.
The table is populated with data from the storage as it should, and selecting a row changes the textField value.
Editing the textfield changes the corresponding table row as it should, but it does not change the NSUserDefaults!
If I relaunch the app, the changes are not saved.
BTW, if I add/remove rows from the table - it is persisted, but changes to row data are not.
It seems like the changes in the NSArrayController selection dictionary are not propagated to NSUserDefaults.
What solved the problem finally was checking "Handles Content as Compound Value" in the content binding preferences of the ArrayController.
Screenshot:

Edit specific row and column of NSTableView programmatically

I want to press a button, and have a specific box in my NSTableView change its value to something else. Is that possible? How can I do this?
Change the model.
That is, get the object you want to change from your array controller, and then modify its attributes.
If you're using a binding, the table will automatically reload the changed cell. If you're using the table view data source methods, just ask the table view to reload the changed cell using -reloadDataForRowIndexes:columnIndexes:.