Row Selection and User Actions in Table Views
Displaying a list of data in a table view is of little use if the user is unable to select the rows. This chapter describes the actions the user can take to select the data rows, how to select rows programmatically, how to retrieve which rows are selected, and the role of the delegate in row selection.
Getting the Current Row Selection
Getting the current table view selection is an oft performed action by an application. The
NSTableView class provides several methods for querying the table view as to its currently selected rows:
selectedRowIndexes is used most often and is recommended. It will provide the full and correct selection regardless of whether a single item is selected or multiple items are selected. The method returns an
NSIndexSet containing the indexes of the selected rows.
selectedRow method returns the index of only the last selected row or
-1 if no row is selected. This is an easiest way to get the current selection if multiple selection is disabled.
numberOfSelectedRows method returns the number of selected rows. It can be used as a shortcut to determine if any objects are selected when empty selection is permitted. Its value can also be used to determine if user interface items should be enabled or disabled if they depend upon multiple items being selected in the table view. For example, if the
numberOfSelectedRows is greater than
1, then you can disable the portions of the user interface that are only relevant when a single item is selected.
isRowSelected: method allows an application to query if a row at a specific index is selected. If it is the method returns
YES, otherwise it returns
Applications often need to iterate over the selected rows. This can be done by iterating over the contents of the selection returned by
selectedRowIndexes or by using the
NSIndexSet Block enumeration method
enumerateIndexesUsingBlock:. An example of using both these techniques are discussed in the “Iterating Through Index Sets” in Collections Programming Topics.
What Happens As Users Change Row Selections?
Users can select multiple rows using the shift key for continuous selections or the command key for non-contiguous selections. See “Make User Input Convenient” in OS X Human Interface Guidelines for more information about user selection actions.
As the user selects rows using the mouse, delegate methods (if implemented) are informed of the changes in row selection. The delegate receives the following messages as changes in the selection occurs by the user. Delegates for table view’s that are managed by Cocoa bindings also receive these same messages and can act on them as required.
selectionShouldChangeInTableView:. Implementation of this method is optional, it is usually implemented when it is necessary to perform validation on editing of a row before allowing the row selection to change.
For example, if the user is editing a row in the table view and the content of that row does not meet the required criteria, the delegate should return
NOfrom this method to prevent the user from changing the selection. If the action was denied it is this method’s responsibility to inform the user as to why the selection change was disallowed and what action they can take to rectify that situation. Returning
YESallows the selection to be changed which is the default behavior if the method is not implemented.
tableViewSelectionIsChanging:. This method informs the delegate that the row selection is about to change due to interaction with the mouse. Keyboard selection does not send invoke this method. Implementation of this method by the delegate is optional.
tableViewSelectionDidChange:. This method informs the delegate that the row selection has changed and that, effectively, the table view selection action is completed. It is sent to the delegate when the user releases the mouse button, whether selection is limited to a single row or multiple selection is enabled.
tableViewSelectionDidChange: messages are notifications. Each is passed an
NSNotification object. Sending the notification instance an
object message returns the table view relevant to the selection change.
A table view delegate can also implement the
tableView:selectionIndexesForProposedSelection: delegate method to allow or disallow the selection of a specific set of rows in a table view. The method is passed the indexes of the rows that are proposed to be selected and then returns the rows that will actually be selected. This allows the user to selectively allow and disallow row selection as appropriate. For example, if the user clicks in an area of the table row that shouldn’t trigger selection this method can be used to prevent that selection from taking place.
The application should be prepared to receive these messages on a continuous basis and, as such, ensure that they are implemented in an optimal fashion.
Allowing Multiple and Empty Selection
A table view can be configured to allow a single row to be selected at once, multiple rows to be selected simultaneously, or to attempt to prevent there from being an empty selection (that a at least one row is always selected). These attributes can be configured in Interface Builder or programmatically.
Programmatically, the table view methods for enabling and disabling these options are set using the following methods:
Selecting and Deselecting Rows Programmatically
NSTableView class provides an instance method to select rows programmatically,
selectRowIndexes:byExtendingSelection: method expects an
NSIndexSet containing the indexes (
0 based) of the rows to be selected, the second parameter specifies whether the current selection should be extended. If
YES, the specified row indexes are selected in addition to any previously selected rows. If the extending selection parameter is
NO, then the selection is changed to the newly specified rows. When this method is called the delegate will only receive the
To deselect a row invoke
deselectRow: passing the index of the row to deselect. When this method is called the delegate will only receive the
There are also two convenience methods that allow the selection and deselection of all the items in the table view. These are primarily intended to be connected to the user interface. The
deselectAll: method will deselect all the selected rows, but only if
selectAll: will select all the table view rows, but only if
YES. Unlike the other programmatic methods, these two methods will invoke
selectionShouldChangeInTableView: on the delegate object, if implemented, followed by
tableViewSelectionDidChange:. If either
selectAll: are invoked without the proper
allows... setting, they are ignored.
Using Type Selection to Select Rows
To simplify navigation in tables or to allow the user to select items without using the keyboard, table view supports type selection. When enabled (by default it is disabled) when a table view is selected you can type the first few letters of an entry and the table view content will be searched for a matching row. Type selection can be enabled and disabled using the
setAllowsTypeSelect: method passing
NO. The default is
How type select figures out which rows to match against is determined by the delegate method
tableView:typeSelectStringForTableColumn:row:. This delegate method returns a string which type select uses for matching.
tableView:typeSelectStringForTableColumn:row: method is not implemented by the delegate the behavior is to invoke
preparedCellAtColumn:row: passing the column index and row and then returns the
stringValue. This allows type select to work on the values in any column and row in the table view. To restrict type select return nil for columns that should be excluded. The following method implementation only allows type select to match values in the “name” column.
- (NSString *)tableView:(NSTableView *)tableView typeSelectStringForTableColumn:(NSTableColumn *)tableColumn
if ([[tableColumn identifier] isEqualToString:@"name"])
NSUInteger tableColumnIndex=[[tableView tableColumns] indexOfObject:tableColumn];
return [[tableView preparedCellAtColumn:tableColumnIndex
Implementing the delegate method
tableView:nextTypeSelectMatchFromRow:toRow:forString: allows the delegate to further customize type selection to match only between a specific selection of rows. It is passed the current type selection string and is expect to compare the appropriate values within the selected rows and return the row to select or
-1 if no row matches.
tableView:shouldTypeSelectForEvent:withCurrentSearchString: method provides the delegate the option to allow or disallow type selection for a particular keyboard
NSEvent. You’d implement this method to prevent certain characters from causing type selecting. For example, if the event contains the ‘space’ character and the search string parameter is
nil, the appropriate action may be to show a QuickLook preview of the selected table view item rather than type selection. However, if the search string parameter is non-
nil then the ‘space’ character would likely be used to extend the type selection.
© 2011 Apple Inc. All Rights Reserved. (Last updated: 2011-07-06)