What is an easy way to set up my NSTableView with multiple columns to only display certain data in one column. I have the IBOutlets set up, but I don't know where to go from there.
问题:
回答1:
Assuming you're not using Cocoa Bindings/Core Data, you can display data in an NSTableView by implementing two methods from the NSTableViewDataSource protocol. Typically your controller will implement the protocol, so open the controller .m file and add these methods to the controller's @implementation
:
- (NSInteger)numberOfRowsInTableView:(NSTableView*)tableView {
return 25; // fill this out
}
– (id) tableView:(NSTableView*)tableView
objectValueForTableColumn:(NSTableColumn*)column
row:(int)row {
return row % 3 ? @"Tick..." : @"BOOM!"; // fill this out
}
You need to set the table's dataSource
property to the controller. In Interface Builder control-drag from the table view to the controller and set dataSource
. Now build and run and you should see your data in the table.
If you only want to fill out one column, add an IBOutlet NSTableColumn* to your controller; let's call it explosiveColumn
. In Interface Builder, control-drag from the controller to the column you want to fill in and set explosiveColumn
. Then, in tableView:objectValueForTableColumn:row: you can test if the column
parameter is the same object as the one that the outlet is set to:
– (id) tableView:(NSTableView*)tableView
objectValueForTableColumn:(NSTableColumn*)column
row:(int)row {
if (column == explosiveColumn) {
return row % 3 ? @"Tick..." : @"BOOM!";
} else {
// other columns blank for now
return nil;
}
}
This tutorial might be useful: http://www.cocoadev.com/index.pl?NSTableViewTutorial
回答2:
Here's an example using multiple table views with data source methods and a document based application:
#pragma mark - Data Source Methods
- (NSInteger) numberOfRowsInTableView:(NSTableView *)tv
{
if (tv == racerTableView)
return [racerList count];
else if (tv == vehicleTableView)
return [vehicleList count];
else
return 0; // something wrong here...
}
- (id)tableView:(NSTableView *)tv objectValueForTableColumn:(NSTableColumn *)col
row:(NSInteger)rowi
{
NSString *colid = [col identifier];
if (tv == racerTableView){
NHRacers *racer = [racerList objectAtIndex:rowi];
return [racer valueForKey:colid];
}
else if (tv == vehicleTableView){
NHVehicles *vehicle = [vehicleList objectAtIndex:rowi];
return [vehicle valueForKey:colid];
}
else
return 0; // something wrong here...
}
- (void)tableView:(NSTableView *)tv setObjectValue:(id)obj forTableColumn:(NSTableColumn *)col row:(NSInteger)rowi
{
NSString *colid = [col identifier];
if (tv == racerTableView) {
NHRacers *racer = [racerList objectAtIndex:rowi];
[racer setValue:obj forKey:colid];
}
else if (tv == vehicleTableView){
NHVehicles *vehicle = [vehicleList objectAtIndex:rowi];
[vehicle setValue:obj forKey:colid];
}
else
nil; // something wrong here...
[self updateChangeCount:NSChangeDone];
}
The tableview datasource outlets are set to the File's Owner and the File's Owner has set vehicleTableView and racerTableView to their respective "Table View" in the IB. The colid key checks the identifier (set in IB by selecting the table view column under the "Identity" drop down, while the "Identity Inspector" is shown). These values were chosen to be the KVC (key coding compliant) properties of the classes being displayed in the table views: use lower case first letter (see apple docs for rest).
For example: (in NHVehicles.h)
@interface NHVehicles : NSObject
{
NSUInteger entry;
NSString *name;
NSString *vehicleClass;
}
@property NSUInteger entry;
@property NSString *name, *vehicleClass;
@end
(in NHVehicles.m)
@implementation NHVehicles
@synthesize entry, name, vehicleClass;
@end
for this tableView, "entry", "name" and "vehicleClass" would be typed (w/o ") into the identifier fields for their respective columns.
If you don't want to show some data in the class, simply do not enter the key for the column identifier. A word of caution: I am using Xcode 4.5.1 and I noticed that once I had entered a few keys for a particular column identifiers and then changed my mind about and attempted to clear the text, it complained when I deleted the text from the identifier field (I could no longer leave the field blank for the columns that I had edited). This was not difficult to work around, but it was a surprise.