NSTableView rebuilds all cells when adding only one - macos

I have a view-based NSTableView driven by an NSArrayController bound to a NSMutableArray as the content array.
When I add a new item to the data source, tableView:viewForTableColumn:row: is called for every item in the data source. I would expect the table view to leave existing items alone, and only call this for the new item.
I add a new item via the controller, like this:
[_arrayController addObject:newObject];
How do I prevent the table view from doing this? The performance impact is unacceptable.
Edit: It also clears the user selection

Related

Mac OS X - Adding and Removing Items From an NSOutlineView With Core Data

I want to add and remove items from an NSOutlineView and animate the changing view. In my OutlineViewController scene I have a NSTreeController bound to my Core Data Entity and my ManagedObjectContext. My NSOutlineView's Content and Selection properties are bound to my NSTreeController and the NSOutlineView > Table Cell View > Model Key Path is bound to the associated objectValue.propertyName.
Assume there is an 'Add' button. I am currently calling the NSTreeController's 'insertChild' method and pass in the Entity name. This works exactly as I want except there is no animation. Similar for the TreeController's removeObjectAtArrangedObjectIndexPath method.
I see that the NSOutlineView provides a insertItemsAtIndexes:inParent:withAnimation: method which would provide the animation but I'm unsure if this will liaise with Core Data and insert a new Entity into the model and I'm not sure how to use this to insert a new item as a child of the selected item?
Any advise very welcome.

NSPopupButton not updating when using setValue:forKey: against it's CoreData bound field

I'm working on a CoreData / Document based app. In one area of the UI I've setup a view-mode table with various columns. One column has an NSPopupButton in it with the Selected Index binding setup as Table Cell View.objectValue.startupState.
Picking any of the menu items in the popup will correctly update the startupState attribute on the entity with the index of the menu item clicked and the NSPopupButton text updates as well. I've verified the attribute value is in fact updated by saving, closing, and re-opening the document.
In another column I have an NSPopupButton bound similarly to another attribute in the same entity - Table Cell View.objectValue.mode. Depending on the mode selection it will modify the startupState value through a manual implementation of setMode which does this statement in certain cases:
[self setValue:[[NSNumber alloc] initWithInt:1] forKey:#"startupState"];
The issue I'm having is that the NSPopupButton isn't updating to show the menu item text for the selected index. As before, I saved, closed, and re-opened the document after the above code ran and the correct item was selected / text appeared so I know the setValue call updated the attribute.
Any ideas?
As mentioned in the comments, Volker's suggestion addresses the issue. willChangeValueForKey and didChangeValueForKey messages are needed around the setValue:forKey call like this:
[self willChangeValueForKey:#"startupState"];
[self setValue:[[NSNumber alloc] initWithInt:1] forKey:#"startupState"];
[self didChangeValueForKey:#"startupState"];

How to add an item to an array by clicking a plus navigationBar button

I have an application with a view that have a tableView which is populated with strings from an array, and also have a navBar with a plusButton. What I want is that when I press the plusButton I want to be able to add items to that array.
Add action method (IBAction) to that UIButton that is implemented in table view control class.
Implement in that method adding new object to your array
Reload table view (or call appropriate methods to add row one by one) after modifying array

NSTableView bindings how to add a row

I'm working on a application with the this interface (sorry the language is Dutch):
http://www.flickr.com/photos/pluueer/5756159100/
The Add function (incl. the four NSTextFields) under the NSTableView are to moved to a sheet someday, but for now this is fine. I've set up bindings according to a tutorial (http://cocoadevcentral.com/articles/000080.php), but the tutorial doesn't supply how to add rows in the way I want to (just adds an empty row which you need to edit in the NSTableView).
I've got a connection between the 'Voeg toe' (Dutch for 'Add') button and the Array Controller. But after clicking I get the message:
2011-05-28 23:37:56.149 Hop Calc[4345:a0f] -[__NSPlaceholderDictionary initWithObjects:forKeys:]: number of objects (0) not equal to number of keys (4)
It makes sense, because I've not implemented anything for adding rows, but I just don't know how.
"Add a row to the table" is the wrong way to think of it. Your table represents a collection and a controller provides the information to the table, mediating between the table (view) and the collection (model). Since you mentioned bindings, the collection is likely managed by an NSArrayController. So you want to add a new object (of the kind your array controller manages) to the array controller's content array.
Simplest way: Connect the Add button to the -add: action of the NSArrayController. It'll add an empty row.
If you want more control, connect the Add button to your own custom action in some controller. That action will create an instance of whatever's represented by your array controller, prepopulate it (or whatever you want to do), then, using an outlet it holds to your NSArrayController, will call the array controller's -addObject: method to add the object (the possibly a -rearrangeObjects call to get the array controller to re-sort its contents).

Can i separate the selection model from an NSTableView

Is there any way how i can maintain my own data model of selected items in a NSTableView.
I find it either pretty slow or complicated to keep the state of selected items when i update the table model.
You can maintain your own NSMutableIndexSet for the selected row indexes. If you're binding the table view's columns to an array controller's arrangedObjects and the array controller's contentArray to an array you own, bind the array controller's selectedIndexes to your index set. If you're implementing a data source, be the view's delegate as well and implement the delegate methods relevant to managing the selection.

Resources