Example code programming Objective-C with Cocoa in Xcode and Interface Builder (Leopard)

25: Display, add and delete data from an NSTableView

Implement NSTableView.

Problem: To create a 3 collumn NSTableView, with ability to edit entries, insert rows and delete rows.

Implementation.

Create a new project in XCode: File->New Project->Cocoa Application
Call it: 025-NSTableView

Now create the classes: MyDataObject of type NSObject, MyTableController of type NSControl.
(Note it need not be of type NSControl!)
Code these as shown below and save.

Note that MyTableController is the Data Source for the NSTableView which expects to find there the methods:
- (int)numberOfRowsInTableView:
- (id) tableView:objectValueForTableColumn:row:
- (void)tableView:setObjectValue:forTableColumn:row:

Note also that although I have made MyTableController not only the Data Source for the NSTableView but also its Delegate, I have not used any of its delegate methods.

The following links I found useful:
CocoaDev: NSTableView
CocoaDev: NSTableViewTutorial
CocoaDev: AnotherNSTableViewTutorial
O'Reilley MacDevCenter: Understanding the NSTableView Class
Rixstep: NSTableView
Quickies for NSTableView
And ofcourse NSTableView Class Reference

// MyDataObject.h // 025-NSTableView // #import <Cocoa/Cocoa.h> @interface MyDataObject : NSObject { NSString *nsStrName1; NSString *nsStrName2; NSString *nsStrName3; } @property (copy) NSString *nsStrName1; @property (copy) NSString *nsStrName2; @property (copy) NSString *nsStrName3; - (id)initWithString1:(NSString *)pStr1 andString2:(NSString *)pStr2 andString3:(NSString *)pStr3; @end // MyDataObject.m // 025-NSTableView // #import "MyDataObject.h" @implementation MyDataObject @synthesize nsStrName1; @synthesize nsStrName2; @synthesize nsStrName3; - (id)initWithString1:(NSString *)pStr1 andString2:(NSString *)pStr2 andString3:(NSString *)pStr3 { if (! (self = [super init])) { NSLog(@"MyDataObject **** ERROR : [super init] failed ***"); return self; } // end if self.nsStrName1 = pStr1; self.nsStrName2 = pStr2; self.nsStrName3 = pStr3; return self; } // end initWithString1:andString2:andString3: @end // MyTableController.h // 025-NSTableView // #import <Cocoa/Cocoa.h> #import "MyDataObject.h" //@interface MyTableController : NSControl { @interface MyTableController : NSObject { NSMutableArray * nsMutaryDataObj; IBOutlet NSTableView * idTableView; } @property (assign) NSMutableArray * nsMutaryDataObj; @property (assign) NSTableView * idTableView; - (IBAction)addAtSelectedRow:(id)pId; - (IBAction)deleteSelectedRow:(id)pId; - (void)addRow:(MyDataObject *)pDataObj; - (int)numberOfRowsInTableView:(NSTableView *)pTableViewObj; - (id) tableView:(NSTableView *)pTableViewObj objectValueForTableColumn:(NSTableColumn *)pTableColumn row:(int)pRowIndex; - (void)tableView:(NSTableView *)pTableViewObj setObjectValue:(id)pObject forTableColumn:(NSTableColumn *)pTableColumn row:(int)pRowIndex; @end // MyTableController.m // 025-NSTableView // #import "MyTableController.h" @implementation MyTableController @synthesize nsMutaryDataObj; @synthesize idTableView; - (void)awakeFromNib { self.nsMutaryDataObj = [[NSMutableArray alloc]init]; int i; for (i = 0; i < 10; i ++) { NSString * zStr1 = [[NSString alloc]initWithFormat:@"%d",(i+1)*10]; NSString * zStr2 = [[NSString alloc]initWithFormat:@"%d",(i+1)*100]; NSString * zStr3 = [[NSString alloc]initWithFormat:@"%d",(i+1)*1000]; MyDataObject * zDataObject = [[MyDataObject alloc]initWithString1:zStr1 andString2:zStr2 andString3:zStr3]; [self.nsMutaryDataObj addObject:zDataObject]; } // end for [idTableView reloadData]; } // end awakeFromNib - (IBAction)addAtSelectedRow:(id)pId { if ([idTableView selectedRow] > -1) { NSString * zStr1 = @"Text Cell 1"; NSString * zStr2 = @"Text Cell 2"; NSString * zStr3 = @"Text Cell 3"; MyDataObject * zDataObject = [[MyDataObject alloc]initWithString1:zStr1 andString2:zStr2 andString3:zStr3]; [self.nsMutaryDataObj insertObject:zDataObject atIndex:[idTableView selectedRow]]; [idTableView reloadData]; } // end if } // end deleteSelectedRow - (IBAction)deleteSelectedRow:(id)pId { if ([idTableView selectedRow] > -1) { [self.nsMutaryDataObj removeObjectAtIndex:[idTableView selectedRow]]; [idTableView reloadData]; } // end if } // end deleteSelectedRow - (void)addRow:(MyDataObject *)pDataObj { [self.nsMutaryDataObj addObject:pDataObj]; [idTableView reloadData]; } // end addRow - (int)numberOfRowsInTableView:(NSTableView *)pTableViewObj { return [self.nsMutaryDataObj count]; } // end numberOfRowsInTableView - (id) tableView:(NSTableView *)pTableViewObj objectValueForTableColumn:(NSTableColumn *)pTableColumn row:(int)pRowIndex { MyDataObject * zDataObject = (MyDataObject *) [self.nsMutaryDataObj objectAtIndex:pRowIndex]; if (! zDataObject) { NSLog(@"tableView: objectAtIndex:%d = NULL",pRowIndex); return NULL; } // end if NSLog(@"pTableColumn identifier = %@",[pTableColumn identifier]); if ([[pTableColumn identifier] isEqualToString:@"Col_ID1"]) { return [zDataObject nsStrName1]; } if ([[pTableColumn identifier] isEqualToString:@"Col_ID2"]) { return [zDataObject nsStrName2]; } if ([[pTableColumn identifier] isEqualToString:@"Col_ID3"]) { return [zDataObject nsStrName3]; } NSLog(@"***ERROR** dropped through pTableColumn identifiers"); return NULL; } // end tableView:objectValueForTableColumn:row: - (void)tableView:(NSTableView *)pTableViewObj setObjectValue:(id)pObject forTableColumn:(NSTableColumn *)pTableColumn row:(int)pRowIndex { MyDataObject * zDataObject = (MyDataObject *) [self.nsMutaryDataObj objectAtIndex:pRowIndex]; if ([[pTableColumn identifier] isEqualToString:@"Col_ID1"]) { [zDataObject setNsStrName1:(NSString *)pObject]; } if ([[pTableColumn identifier] isEqualToString:@"Col_ID2"]) { [zDataObject setNsStrName2:(NSString *)pObject]; } if ([[pTableColumn identifier] isEqualToString:@"Col_ID3"]) { [zDataObject setNsStrName3:(NSString *)pObject]; } } // end tableView:setObjectValue:forTableColumn:row: @end

Bring up Interface Builder by double clicking on MainMenu.nib.

Drag a NSTableView and two buttons onto the window and name them as shown.

Note: to insert the third collumn go to the Attributes panel of the Inspector and set the number of collumns to three.

Note: to make the collumns of equal size select the NSScrollView, go into the Size panel of the Inspector and set the width of the view to 3n + 26, where n is the required width of each collumn and 26 is for the rhs scroll bar.
Next, select each collumn in turn and set its width to n. In my example n = 95.

XCode,Interface Builder - Do the layout

Interface Builder: Do the layout

XCode,Interface Builder - Set the number of NSTableView collumns to 3

Set the number of NSTableView collumns to 3

Select each collumn in turn and in the Attributes panel of the Inspector give it an identifier by which to identify it in the code. Here the identifier is Col_ID1.

Set the collumn identifier

Interface Builder: Set the collumn identifier to Col_ID1

Drag an NSObject onto the MainMenu.xib and set the object to MyTableController.

XCode,Interface Builder - set NSObject to MyTableController

Interface Builder: set NSObject to MyTableController

Select the NSTableView and in the Connections panel of the Inspector set the DataSource and Delegate outlets to MyTableController.

Interface Builder - set DataSource and delegate to be MyTableController

Interface Builder: set DataSource and delegate to be MyTableController

Link the idTableViewOutlet of MyTableController to the NSTableView.

XCode,Interface Builder - Link MyTableController to the NSTableView

Interface Builder: Link MyTableController to the NSTableView

Link the two buttons to their respective IBActions in MyTableController.

Save everything and Run.

XCode,the working NSTableView Application

the working NSTableView Application

If you want to download the code

Click the Download Link to obtain 025-NSTableView.zip file of this whole OS X 10.5 Leopard program.

Download 025-NSTableView.zip (2.3 MB)



Please send me your comments

If you include your e-mail I may reply!  

Page last modified: 18:58 Sunday 12th. May 2013

Julius Guzy

Paintings & Drawings

  • Link to drawing made from painting by Rubens of the Feast of Venus

animatedPaint