Populating View-Based Table Views Programmatically
In order to populate a view-based table view programmatically you must implement to protocols: the NSTableViewDataSource and the NSTableViewDelegate. Both protocols contain methods that are essential to providing the content and creating the cells for the table view.
This chapter consists of two examples. The first uses a simple text field for the cell of the table view. The second uses a custom cell that has been defined in Interface Builder.
The Required Methods
In order to function, a programmatically implemented view-based table must implement the following:
The
numberOfRowsInTableView:method that is defined by theNSTableViewDataSourceprotocol. This method provides the table with the number of items it needs to display.The
tableView:viewForTableColumn:row:method that is defined by theNSTableViewDelegate Protocol. This method both provides the table with the view to display as the cell for the specific column and row, as well as populates that cell with the appropriate data.
For this simple example assume delegate and datasource are implemented in the same class (which must therefore conform to both protocols) and that the content is stored in the property nameArray which is an array of name strings, also stored in the same class.
Implementing the Datasource
The datasource method is a simple implementation, but is required for the table to work.
The code in Listing 4-1 shows the implementation.
Listing 4-1 NSTableViewDelegate implementation of numberOfRowsInTableView
- (NSInteger)numberOfRowsInTableView:(NSTableView *)tableView { |
return nameArray.count; |
} |
The datasource implementation of the method simply returns the number of items in the array.
Implementing the Delegate
The NSTableViewDelegate is responsible for providing the cell that is displayed in the table view, along with implementing any target-action or notification code so that it can interact with the delegate. What follows are two simple implementations of tableView:viewForTableColumn:row: that would allow displaying the content of the namesArray model object.
Creating and Configuring an NSTextField Cell
The NSTableViewDelegate method tableView:viewForTableColumn:row: is where the cell that is displayed in the table view is created and configured. The pseudo-code in Listing 4-2 creates an NSTextField as the cell and populates it with the appropriate name for the row.
Listing 4-2 Simple Table View’s tableView:viewForTableColumn:row: Implementation
- (NSView *)tableView:(NSTableView *)tableView |
viewForTableColumn:(NSTableColumn *)tableColumn |
row:(NSInteger)row { |
// get an existing cell with the MyView identifier if it exists |
NSTextField *result = [tableView makeViewWithIdentifier:@"MyView" owner:self]; |
// There is no existing cell to reuse so we will create a new one |
if (result == nil) { |
// create the new NSTextField with a frame of the {0,0} with the width of the table |
// note that the height of the frame is not really relevant, the row-height will modify the height |
// the new text field is then returned as an autoreleased object |
result = [[[NSTextField alloc] initWithFrame:...] autorelease]; |
// the identifier of the NSTextField instance is set to MyView. This |
// allows it to be re-used |
result.identifier = @"MyView"; |
} |
// result is now guaranteed to be valid, either as a re-used cell |
// or as a new cell, so set the stringValue of the cell to the |
// nameArray value at row |
result.stringValue = [self.nameArray objectAtIndex:row]; |
// return the result. |
return result; |
} |
This pseudo-code shows the basic implementation required to use an NSTextField as the cell for the table column. It can be assumed that this is a single column table.
First makeViewWithIdentifier:owner: is called passing the identifier @”MyView”. This is to determine if there is already an available cell in the pool of available cells that can be reused. If a cell is available, the code skips to the assignment of the stringValue of the text field which is set to the nameArray value at row, and the result is returned.
However if no cell with the identifier @”MyView” is available, then a new text field is created (note that it is autoreleased). It then has its identifier set to @”MyView” so that it will be reusable when the opportunity arises. Finally, as with the first case, the stringValue of the text field is set to the correct name and returned.
Acquiring a Cell from Interface Builder
The most likely situation is that you will have designed a cell in Interface Builder and will want to fetch it and then populate the values in that cell. The implementation for that is shown in Listing 4-3. This example assumes that there is a table create in Interface Builder with a column identifier @”MyView” with a view-cell also with the identifier @”MyView”.
Listing 4-3 NSTableViewDelegate implementation of tableView:viewForTableColumn:row: using Interface Builder for the content
- (NSView *)tableView:(NSTableView *)tableView |
viewForTableColumn:(NSTableColumn *)tableColumn |
row:(NSInteger)row { |
// Retrieve to get the @"MyView" from the pool |
// If no version is available in the pool, load the Interface Builder version |
NSTextField *result = [tableView makeViewWithIdentifier:@"MyView" owner:self]; |
// or as a new cell, so set the stringValue of the cell to the |
// nameArray value at row |
result.stringValue = [self.nameArray objectAtIndex:row]; |
// return the result. |
return result; |
This implementation is straightforward. It retrieves the view with the @”MyView” identifier from the pool of reusable objects. If there is no reusable version, it looks in Interface Builder for a matching table column and cell with the identifier. Once found it is returned and your application need only set the string value.
In both these simple cases there is no action required by the cell. If the view-cell contained buttons, or allowed editing, or was required to interact with the delegate it would be required to use target-action or notifications to work with the delegate. See the “Complex TableView” in TableViewPlayground for an example of how to implement that behavior.
© 2011 Apple Inc. All Rights Reserved. (Last updated: 2011-07-06)