Avatar of Alex

by

Using Cocoa Bindings for binding DADataTable to NSTableView.

February 15, 2010 in Cocoa, Data Abstract, RemObjects, Uncategorized, Xcode

As you might know, Cocoa offers several ways for populating NSTableView with data.
The first approach is to use the NSTableViewDataSource protocol, which we are applying widely in our samples.

The second approach I want to cover today, is using Cocoa Bindings.

What is Cocoa Bindings?

Cocoa Bindings is an amazing technology that allows us to establish a full two-way data binding without writing any “glue” code. Cocoa Bindings widely uses the MVC paradigm, where models encapsulate application data, view display and edit data and controllers mediate between model and view.

So firstly, we will need to implement our own DataTableController, which we can reuse for any future projects.

In order to avoid creating a new sample from scratch, I’ve used our DASimpleSample, from which I removed all code for filling NSTableView using the NSTableViewDataSource protocol.

Implementing our DataTableController:

As the base for our controller, we will take the NSArrayController class.

So, let’s create a new class called DataTableController, inherit it from NSArrayController, add the DADataTable instance variable, which represents our data table and expose it as the read/write property like on code-snipped below:

//  DataTableController.h
 
#import <DataAbstract/DataAbstract.h>
 
@interface DataTableController : NSArrayController
{
	DADataTable *table;
}
 
@property (retain) DADataTable *table;
 
@end

In the DataTableController.m file we need to implement the setTable method, which retains the given DADataTable and set the table rows as content property of our controller.

-(void)setTable:(DADataTable *)newTable
{
	[newTable retain];
	[table release];
	table = newTable;
	[self setContent:[table rows]];
}

Also, in order to allow our controller to add and delete rows, we need to override add and remove methods as shown below:

-(void)add:(id)object
{
	if (!table) return;
	DADataTableRow *newRow = [table addNewRow];
	[self rearrangeObjects];
	[self setSelectedObjects:[NSArray arrayWithObject:newRow]];
}
 
-(void)remove:(id)object
{
	if (!table) return;
	for (DADataTableRow *row in [self selectedObjects])
		[table removeRow:row];
	[self rearrangeObjects];
	[self selectNext:self];
}

That’s all, our controller is ready. Let’s see how to use it for binding data.

Binding DataTable:

Open MainMenu.xib in Interface Builder and add NSArrayController.

Then, having added the selected controller, go to the Identity Inspector and select DataTableController as the class of the controller.

Then open Attributes Inspector and add keys. Keys is the column name of our DataTable. Specifying keys will allow us to select appropriate values in binding columns.

Now go to our window, select the NSTableView control and bind each of its columns to our controller.

For that, you will need to select a column and, in the Binding Inspector tab in the Value section, choose Bind To: Data Table Controller, set arrangedObjects as Controller Key and put the appropriate column name in the Model Key Path combo-box. We should get something like this:

Finally, we will set a link between add/remove methods and our controller.

To do that, we have to expand the toolbar of our application, then open the HUD window for our controller by performing a right mouse button click on it and connect add: and remove: actions with the appropriate toolbar buttons. You will see something like this:

We are now finished with the visual part and can close Interface Builder. The last thing to do is to set the content of our controller to a specific table. Switch to XCode and modify the asyncRequest: didReceiveTable: method as shown below:

- (void)asyncRequest:(DAAsyncRequest *)request didReceiveTable:(DADataTable *)table
{
	workersTable = [table retain];
	// set our table...
	[tableController setTable:workersTable];
}

That’s All. Let’s compile and run our application to see the results.

We can edit/insert/delete rows, all should work as expected and all the configuration took place in Interface Builder, we just had to write one line of code.

[tableController setTable:workersTable];

In the next my blog post, I’m going to tell you more about Cocoa Bindings. We will, among other things, try to add the client-side filtering of data in the table, the highlighting of changed cells.

Comments are closed.