NSArrayControllers and binding – an example

NSArrayControllers can save you precious time (and lines) if your app basically deals with a NSMutableArray, in any form.

In this tutorial I’ll explain how to use NSArrayControllers to bind a data source and a view together and allow edition of the data.

The basics

For the set-up, you’ll first want to create a new Cocoa project, and create a custom class to hold your data. In this example, I will create a TaskList class, consisting of three instance variables : taskName, description and priority. As for now, I only need to write the getters and setters; my TaskList.h file will look like this :

#import <Cocoa/Cocoa.h>

@interface TaskList : NSObject  {
	NSString * taskName;
	int priority;
        NSString * description;
}

-(int)priority;
-(void)setPriority:(int)aValue;

-(NSString*)taskName;
-(void)setTaskName:(NSString*)aName;

-(NSString*)description;
-(void)setDescription:(NSString*)aDescription;

@end

And my TaskList.m file will look like this :

#import "TaskList.h"

@implementation TaskList 

-(id)init
{
     if ( self = [super init]) {
        [self setTaskName:@"New Task"];
        [self setPriority:1];
        [self setDescription:@"<To Do>"];
    }
    return self;
}

-(int)priority{ return priority;}
-(void)setPriority:(int)aValue { priority = aValue;}

-(NSString*)taskName{ return taskName;}
-(void)setTaskName:(NSString*)aName
{
    if (aName != taskName) {
        [taskName release];
        [aName retain];
        taskName = aName;
    }
}

-(NSString*)description{ return description; }
-(void)setDescription:(NSString*)aDescription
{
    if (aDescription != description) {
        [description release];
        [aDescription retain];
        description = aDescription;
    }
}
@end

Once this is done, we’ll set up the UI and add the NSArrayController in Interface Builder. The NSArrayController will basically take care of handling the data for us – but we will need to provide him with the datasource, and the bindings we want to use.

The UI

Double-click on MainMenu.nib to open it in Interface Builder. to the existing window, add a NSTableView with two column, an “Add” NSButton and a “Remove” NSButton. You can also add a NSTextField (that will hold the number of our objects) and another NSTextField that will hold the description for the task. An example is shown below :

Now add an NSArrayController (from the Cocoa-Controllers palette) to your Nib file. In the inspector palette for you NSArrayController, change the ‘Object Class Name’ to ‘TaskList’, and uncheck ‘Preserves selection‘. Add three keys below, taskName, priority and description. These will be the keys we’ll be using for the bindings.

The bindings

The first column of our table view should display, let’s say, our task name. Select the column, and in the bindings page of the inspector, bind value to the keyPath taskName of ‘arranged objects’ :

You can do the same for the other column, binding it to priority. Then, bind the description NSTextField value to the keyPath description of ‘arranged objects’, and the number NSTextField value to the keyPath @count of ‘arranged objects’.

Then, control-drag between the two buttons and the NSArrayController to make it the target, with the actions ‘insert’ and ‘remove’. You can also bind the remove button’s ‘enabled’ binding to the ‘canRemove’ attribute of the controller (this will prevent the user from clicking the button when the selection is null, for instance).

You’re all set ! Build and run, and your application is fully functional… (well, it doesn’t do much … but…):

If you want to add some saving and loading possibilities, you can now create a standard controller for your app, and make it conform to the NSCoding protocol …

About these ads

9 Responses to “NSArrayControllers and binding – an example”


  1. 1 Eimantas June 2, 2008 at 3:34 pm

    You should totally use properties (new in Objective-C 2.0). They would save you tons of code writing in TaskList model:

    In header:
    1) provide three instance variables
    2) define them as properties with @property directive
    3) use @synthesize directive in implementation to create accessor methods to these variables

    Other than that – great tutorial!

  2. 3 Cyril June 2, 2008 at 7:11 pm

    very true … the problem being I still can’t afford to buy a new Mac and Leopard – so I’m stuck with 10.4, and Xcode 2.5 …

  3. 4 decoder December 9, 2009 at 5:10 pm

    A very good tutorial for beginners.

    Nice Work!

  4. 5 Chris November 23, 2011 at 4:23 pm

    That should be “editing of the data” not “edition of the data” :-)

  5. 7 King January 2, 2012 at 7:35 am

    Its a good example for dummies in bindings

  6. 8 dante lee August 6, 2012 at 1:42 pm

    very simple but translated a lot. thank you very much.

  7. 9 Daniel H. Moran June 30, 2013 at 6:14 pm

    This was very helpful, thank you!

    I have a “quick” question though…

    when a “new” object is init’d. I’d like to set a “Name” property to be something like “Action #[total number of items in list]”

    How do you access the array from the object.m “init” function in order get the count of total number of items in the list?

    Also is there a way to change the position of a row in the tableview list?


Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s




Talking about Cocoa

Here is a little blog dealing with Mac programming : snippets, technology, ...

Categories


Follow

Get every new post delivered to your Inbox.

%d bloggers like this: