Cocoa- Using representedObject for NSButton in NSCollectionView - objective-c

Setup
I have a NSCollectionView. I have a checkbox in the View Prototype. I've successfully set up bindings so the Card Title and action get populated. (image 1, below)
Goal
I'd like, when I click the checkbox, to run a function that accesses the specific CardModel that the View Prototype is already able to access. I'll then manipulate its data accordingly.
Research
I found this article on SO: Get the representedObject values of NSCollectionViewItem NSButton click, which describes my situation pretty well. The answer, unfortunately, is without specific code. Here's what's suggested:
So, first, set the represented object of your button's cell to the
collection view item that owns the button. (You can do this in the nib
editor.) Then, in your action method, get the button's cell, then the
cell's represented object (which is the item), then the item's
represented object.
Seems simple enough, right?
Attempted Solution(s)
I create a method cardCheckBoxClicked: and connect it to the checkbox.
As per the advice above, I connect the button cell's outlet representedObject to Card Collection View Item. (image 2)
I then attempt to get the Card Collection View Item's representedObject in code.
From MainWindowController.h:
-(IBAction)cardCheckBoxClicked:(id)sender
{
CardModel* cModel = [[sender representedObject] representedObject];
NSLog(#"card title: %#",cModel.title);
}
Error
When I click on the checkbox, I get the following error:
-[NSButton representedObject]: unrecognized selector sent to instance 0x6080001581b0
Question!
So - how do I access the button cell's represented object? Did I misunderstand the advice given above? How can I successfully access the data I need?
Images (reference)
bindings example
represented object connection

This here:
-[NSButton representedObject]:
Is you asking the Class NSButton to run the method representedObject. Make sure you distinguish between a Class an an object or instance of that class.
You need to take the actual button, get its button cell, (at least I think that's what you want), and then call representedObject on the cell. If I am understanding you correctly. I never touch interface builder, so here's completely made up code that lines up with what you are asking for.
someObject = [[theButton cell] representedObject];

In addition to CH Buckingham's answer, you should also consider using bindings. You can bind the checkbox's value binding to the collection view item with a model key path which goes through representedObject to some property on your CardModel. (If desired, the key path can keep going through your model object graph.) That will set that property whenever the button is toggled.

Related

Clicking on an image in a collection view

I have a collection view and each item has an image and a label. I want to click the NSCollectionViewItem or NSImage and then hide the collection view and display a completely separate view containing the details of the object that was clicked.
I cant find any documentation on how to handle click events in this situation. How is this possible? I have built out the collection view in Interface Builder so everything was done via bindings as opposed to code.
#Jeff, I don't have permissions to add a comment so writing this as answer.
You can overwrite setSelection in your subclass of NSCollectionViewItem (as explained by #indragie in Selection Highlight in NSCollectionView) to track the selected item and perform an action.
The solution that I went with was to not actually use an Image Well, aka NSImage. I used a button and bound the Image property to an instance of an NSImage that I exposed as a property on my model.
It was easy enough but I'm shocked more people havent been asking this question.

Get the representedObject values of NSCollectionViewItem NSButton click

I have read some questions and I find some very confusing and I don't really know if they answer my question.
I have an NSCollectionView implemented and connected to a Core Data context, everything shows correctly.
Now what I have is buttons in the view prototype, and when I click this buttons I need to get the value of the representedObject of that cloned view.
I have read and read and some parts are confusing to me, so I'm looking for a simple explanation.
Thank you for your time.
An action method takes one argument:
- (IBAction) collectionViewButtonClicked:(id)sender {
}
That sender is the control or other UI element (e.g., menu item) that sent the message.
With that argument, when your action method gets called, you know which button was clicked.
A button is a kind of control, and every control is backed by at least one cell. Cells have represented objects, too.
So, first, set the represented object of your button's cell to the collection view item that owns the button. (You can do this in the nib editor.) Then, in your action method, get the button's cell, then the cell's represented object (which is the item), then the item's represented object.
If the representedObject outlet doesn't show up in the nib editor, you probably have the button selected, not its cell. I recommend opening the nib editor's outline view using the button in the lower-left and then never, ever closing it.

Custom NSPopUpButtonCell outlet / bindings

I'm having a problem with a custom NSPopUpButtonCell in a table that's instantiated when the table view is populated via bindings and a NSArrayController.
The pop up button cell is created but when attempting to access the outlet by overriding the pop up button cell's setMenuItem:item method it's nil.
Is this the expected behaviour..?
Should another method be used to replace the menu at creation time?
Basically I need the outlet to link back to my controller (NSWindowController) for that document window so I can customize the NSPopUpButtonCell menu accordingly from the custom popup button when it's populated.
A solution using bindings would be even better - but when overriding setObjectValue: I can see it's only never called with a nil parameter.. using a stock NSPopUpButtonCell results in a properly populated pop up menu, though.
(see also Why is NSPopUpButtonCell showing correctly when only setObjectValue:nil is called).
You don't need to override anything to populate an NSPopUpButtonCell in an NSTableView column. The thing to know is that you set the bindings on the NSTableColumn and not on the cell itself. Typically, you would have an NSArrayController in your xib that is bound to an NSArray containing all the options for the pop-up, and then you would select the column with the pop-up cell and go to it's bindings. Like in this screenshot (note the populated Content, Content Objects, and Selected Object bindings in the inspector on the right):
If you want a working example, you can check out this project I whipped up for another StackOverflow question. There's a bunch of unrelated stuff pertaining to making the NSPopUpButtonCell use NSAttributedStrings, but the bindings in the xib constitute a working example of how to bind an NSTableColumn with a pop-up whose options are populated by bindings.

How can I be notified when a NSComboBox selection changes IF the combo box is dynamically added with a new table row?

I have a NSTableView and each row has a NSComboBox.
The table column is bounded to NSArrayControllerA and each NSComboBox is bounded to NSArrayControllerB.
I would like to be notified when the selected value in any NSComboBox changes.
So far, I've tried to add a listener to the NSArray managed by the NSArrayControllerB, but I'm not notified about any change.
I've also tried to add an observer to the NSTableView, with a NSComboBoxSelectionDidChangeNotification but it seems the notifications are not propagated to the parent views. And the combo boxes are dynamically created when a new row is inserted.
thanks
UPDATE: How is the NSComboBox bound ?
OK. I assume you've bound the combo box's selection to the array controller's selection? If so, try observing the array controller's selectionIndex property. (It's KVO-compliant.)
On my iPhone so I can't easily test right now, but that should do the trick.
OK, scratch that, now that I better understand the question.
How about instead you set the selector for the cell to some method in your controller (with an outlet to the enclosing table view), say, -comboBoxClicked: and then implement something like:
- (void)comboBoxClicked:(id)sender
{
NSUInteger changedRow = [[self tableView] selectedRow];
// Do something with changedRow
}
I did a cursory test (just NSLogging changedRow) and it seemed to work for me, at least in a very basic application.

Creating NSMatrix of NSImageCells

I need to create an NSMatrix with NSImageCells bound to an array controller. So the content of the NSMatrix is bound to an NSArray (so there are as many NSImageCells in the matrix as there are objects in the array), then the image path of the NSImageCells are bound to a key called "iconPath" in the Array Controller.
And then when an image cell is clicked in the matrix, I need it to perform an action. I know how to use bindings, and I have a concept like this working in an NSTableView, but I have never used NSMatrix before, so are there any good resources or sample code that would help me get started with this?
Thanks
If you want them to send actions when you click on them, then you probably want NSButtonCell instead of NSImageCell. A button cell can still contain an image.