Table Views Overview
In the most general terms a table view is made up of rows and one or more columns that display the content of a collection. Each row represents a single item within the data model and each column displays a specific attribute of the model. The user selects rows and then the application can perform the appropriate action on those rows.
Two Variations of Table Views
In OS X v 10.6 and earlier the cells within the table were based entirely on subclasses of NSCell. In this book these tables will be referred to as cell-based table views. While cell-based table views have been a workable solution, it makes visually customizing individual cells and row content very difficult, requiring subclassing and programatically creating your own cell subclasses..
In OS X v 10.7 and later tables now support the use of subclasses of the view class, typically the NSTableCellView class or a subclass, for the cells. In this book these tables are referred to as view-based table views. Using view-based table views allow much more complex and rich cell design in a much simpler manner, most often by using Interface Builder.
View-Based Table Views
View-based table views provide a rich design time opportunity. On its own, the NSTableCellView displays an imageView and textField. This was a common requirement with cell-based table views, and it always required subclassing. You can create instances of NSTableCellView prototype cells in Interface Builder by simply dragging them from the library and dropping them into the appropriate table column. You then have the opportunity to modify the existing subviews, moving, resizing and hiding the cells. VoiceOver support is provided automatically when using NSTableCellView instances, the textField contents are, by default, used as the text to be spoken.
You can also easily subclass NSTableCellView to add additional subviews and functionality. Once the subclass is created, the actual design and layout, can be done entirely within Interface Builder. Using this design allows very flexible and much simpler visual customization. Whether the standard NSTableCellView class or a custom subclass the view can be retrieved programmatically at runtime (or automatically using Cocoa bindings).
Since view classes support animation within their content, you can animate content within NSTableCellView instances by simply using the standard view animation capabilities. In addition, NSProgressIndicator instances simply work within view-based cells, eliminating complicated and timely NSCell subclassing. The TableViewPlayground example uses NSProgressIndicator instances to display content that is loaded lazily. An application that downloads content could use a determinate configured NSProgressIndicator view to show progress, similar to Safari.
Each NSTableCellView instance is inserted as a subview of an NSTableRowView instance. Each row is represented by an instance of NSTableRowView. The row view is responsible for drawing the selection indicator, as well as various (optional) visual styles. An application can override NSTableRowView to add custom background drawing, custom highlighting behavior, and other visual aspects not available as options to the stock row view. An example of a custom row view is a Finder-like row with a colored indicator that is displayed over a portion of the row view background, but still allows selections to be shown.
You typically use Interface Builder to design and layout your NSTableRowView prototype rows within the table. They can then be retrieved programmatically at runtime. Implementation of NSTableRowView subclasses is entirely optional.
Cell-Based Table Views
In earlier versions of OS X all table views were based entirely on subclasses of NSCell that were used to display each cell within the table. Each row and column within the table view is a subclass of NSCell. This was a workable solution that allowed the design of tables using the standard Cocoa controls. However, creating any cells that required content that wasn’t provided by subclasses of NSCell required that you write your own subclasses, which was difficult and time consuming. While a view-based table cell may require writing a custom view, this is much simpler than writing a subclass of a cell.
Cell-based table views are still supported.
New Table View Capabilities
OS X v 10.7 also adds new capabilities to both view-based and cell-based table views.
Tables now support animation of cells as they are moved, inserted and deleted. Various animation modes are provided and they can be grouped to allow changes to happen in batches as multiple changes as you make changes within the table view and the corresponding changes in the model data.
Tables also support drag and drop using both the classic and the new drag and drop methodology. Supporting dragging and dropping of single rows to the Finder now requires that your model object be compliant with the NSPasteboardWriting protocol and has been greatly simplified (although the old model is still supported). Multi-image dragging is also supported in table views, allowing the content being dragged to morph during the drag, dependent on the underly location.
View-based tables re-use cell views which provides an implementation that allows complex views and a multitude of items to exist and use memory effectively. This is discussed further in “Table Views Overview”
Datasource and Delegate
An NSTableView object must have a datasource. Following the Model-View-Controller design pattern:
The datasource class (
NSTableViewDataSource) mediates between the table view and the table view’s model data. The datasource is also responsible for implementing the support for providing the table the model data in a pasteboard format that allows both copying of data and dragging of rows. The datasource is also responsible for determining whether incoming drag actions are valid and how they should be handled.The delegate class (
NSTableViewDelegate Protocol) allows the customization of the table view’s behavior without requiring the subclassing of the table view. It supports table column management, the type-to-select functionality, whether or not specific rows should allow selection, amongst other methods.
The datasource and the delegate are often (but not necessarily) the same object. The responsibilities of the datasource and delegate objects will differ based on whether a table view is cell-based or view-based. The responsibilities of both the delegate and datasource classes differ when Cocoa bindings are used for populating tables.
View-Based Table Views
When creating view-based tables, the datasource object must adopt the NSTableViewDataSource protocol and the delegate object must adopt the NSTableViewDelegate Protocol. When programmatically populating a view-based table view, there are methods that must be implemented in both the datasource and the delegate. This is discussed further in “Populating View-Based Table Views Programmatically.” Implementing the datasource method is not required when using Cocoa bindings, while implementing the delegate method is optional.
While the NSTableViewDataSource protocol defines a method that allows editing of table view cells, this method must not be used with view-based table views. Instead you must use the target-action methodology in order to edit the content. Examples are shown in “View-Based Table Views.”
Cell-Based Table Views
Cell-based table views are similar to view-based table views in that they have a datasource that adopts the the NSTableViewDataSource protocol and an optional delegate that adopts the NSTableViewDelegate Protocol that allows customization of the table view behavior.
Cell-based table views must implement the NSTableViewDataSource method numberOfRowsInTableView: that tells the table view how many rows it has to display. It must also implement the method that returns the data that is displayed in the each column cell tableView:objectValueForTableColumn:row:. If the table view data is editable, then a method to allow the updating the model values can be implemented. This is discussed in detail in “Populating Cell-Based Table Views.” Again, when using Cocoa bindings for populating a cell-based table view, the datasource methods that are required for programmatic populating are not necessary.
© 2011 Apple Inc. All Rights Reserved. (Last updated: 2011-07-06)