I have a NSTableView with 3 columns. I can sort using any of the colunms by clicking on the column header. Here is my issue though: I am presorting the array and then loading it in NSTableView so the initial TableView is already sorted by the values in one of the 3 columns. Now when I click on the column headers, i can resort and the small ascending/descending image ( triangle) appears indicating how the sort order is. What I want is, to be able to display this ascendingimage triangle in the column header right at the start when the NSTableView is loaded the first time, for the column based on which I have already sorted the Array. Thanks in advance :)
Thanks Peter and cb160. So I added this in my refreshList method:
The *lastColumn parameter has the right identifier if i display it using NSLog, but still that triangle image does not get loaded when the table loads data the first time. Is there something I am missing here ?
My table View is setup like this:
-(IBAction)refreshList:(id)sender
{
//setup array here and sort the array based on one column. This column has
identifier 'col1' and it works as expected
// trying to set the sortindicator image for the column here
NSTableColumn *lastColumn;
lastColumn = [aTableView tableColumnWithIdentifier:#"col1"];
[aTableView setIndicatorImage:[NSImage imageNamed:#"NSDescendingSortIndicator"]
inTableColumn:lastColumn];
[aTable reloadData];
}
- (int) numberOfRowsInTableView:(NSTableView *)aTable
{ // return count of array
}
- (id)tableView:(NSTableView *)aTable objectValueForTableColumn: (NSTableColumn *)
tableColumn row:(int)row
{
//set up arrays here to load data in each column
}
- (void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray
*)oldDescriptors
{
//sort here when column headers are clicked
}
You can use the -setIndicatorImage:inTableColumn: method on NSTableView to do this.
You can use the strings NSAscendingSortIndicator and NSDescendingSortIndicator to use the built in images (with UIImage's +imageNamed: method.)
You can get the NSTableColumn * parameter for this method using the -tableColumnWithIdentifier: method on NSTableView. Set the idenitfier in the column using the identifier attribute in Interface Builder (see below)
Related
How can I have more than 2 values held by my table view cell? What I want to happen is when I click a cell in my table view, it will pass 3 values to the next view. But I can only get two values (name, address) because they are contained in the textlabel and detailtextlabel but the (phone) is not being showed in my cells, only name and address.
If u want to display more value in cell the create custom cell.
Option is use NSMutableArray with like below and show all values in custom cell:
NSMutableArray *arrValues = [[NSMutableArray alloc] initWithObjects:[NSArray arrayWithObjects:"Value1","Value2","Value3"],nil];
Add as many array into arrValues.
Now when tableViewDidSelectAtRow 's method: pass this array to next controller
NSArray *arrPassing = [arrValues objectAtIndex:indexPath.row];
create a custom cell for the tableview cell
I have two coloumn in NSTableView as Name and Salary with 5-10 values. I want to sort these coloumn after click on header of both the column. There is lots of data present in Internet but I am not able to use these. Please help me to do this in cocoa.
Thanks in advance and appreciate any help.
Each table column has a method setSortDescriptorPrototype
Sort descriptors are ways of telling the array how to sort itself (ascending, descending, ignoring case etc.)
Iterate over each of the columns you want as sortable and call this method on each of those columns, and pass the required sort descriptor (In my case I'll be using the column identifier)
for (NSTableColumn *tableColumn in tableView.tableColumns ) {
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:tableColumn.identifier ascending:YES selector:#selector(compare:)];
[tableColumn setSortDescriptorPrototype:sortDescriptor];
}
After writing this piece of initialization code, NSTableViewDataSource has a method - (void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors that notifies you whenever a sort descriptor is changed, implement this method in the data source and send a message to the data array to sort itself
- (void)tableView:(NSTableView *)aTableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
self.data = [self.data sortedArrayUsingDescriptors:sortDescriptors];
[aTableView reloadData];
}
This method will get fired each time a column header is clicked, and NSTableColumn shows a nice little triangle showing the sorting order.
I stumbled upon this question while looking for the easiest way of implementing something similar. Although the original question is old, I hope someone finds my answer useful! Please note that I am using Xcode 5.1.1
Ok so to do this you need to:
select the actual column you want to sort in your table.
In your Attributes Inspector you need to fill in two fields: Sort Key, and Selector.
In the Sort Key field, you need to enter the value of your Identifier. The value of your Identifier is located in your Identity Inspector.
In the Selector field you need to enter a suitable selector method based on the object type in the column. The default method is; compare:
Based on the Table View Programming Guide for Mac. The compare: method works with NSString, NSDate, and NSNumber objects. If your table column contains only strings, you may want to consider using the caseInsensitiveCompare: method if case sensitivity is unimportant. However, consider replacing these method signatures with the localizedCompare: or localizedCaseInsensitiveCompare: methods to take into the account the user’s language requirements.
Finally, you need to declare the tableView:sortDescriptorsDidChange: method in your Table View Controller in the format shown below:
-(void)tableView:(NSTableView *)mtableView sortDescriptorsDidChange:(NSArray *)oldDescriptors
{
[listArray sortUsingDescriptors: [mtableView sortDescriptors]];
[tableView reloadData];
}
Just had lately the same issue to get tableView sorted.
My approach :
bind your sortDescriptors to tableview's arrayController
bind tableview's sortDescriptors to Arraycontroller's sort descriptor
perform the settings in attribute inspector (see Tosin's answer above)
Worked perfect for me. No need to set prototypes for columns or something else.
Thanks very much ,It is usefullly for my question.
my code like this
First, set unique values in the XIB interface,like name...
- (void)viewDidLoad {
[super viewDidLoad];
self.itemTableView.dataSource = self;
self.itemTableView.delegate = self;
self.itemTableView.selectionHighlightStyle = NSTableViewSelectionHighlightStyleRegular;
self.itemTableView.usesAlternatingRowBackgroundColors = YES;
for (NSTableColumn *tableColumn in self.itemTableView.tableColumns ) {
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:tableColumn.identifier ascending:NO selector:#selector(compare:)];
[tableColumn setSortDescriptorPrototype:sortDescriptor];
}
}
-(void)tableView:(NSTableView *)tableView sortDescriptorsDidChange:(NSArray<NSSortDescriptor *> *)oldDescriptors{
NSLog(#"sortDescriptorsDidChange:%#",oldDescriptors);
[self.itemArr sortUsingDescriptors:[tableView sortDescriptors]];
[self.itemTableView reloadData];
}
I am making an app where I'll have a tableview with an 'add' button in the navigation bar, and this 'add' button creates a new row, but the problem is I can't figure out how to give rows unique names. To let the user decide the name, I have included an alert with a plain text field. The user should then write the name in the field and the new row will then be called that. But how do I do that?
I have used the tableview template provided in Xcode, which give each row a new name according to the clock they added a new row. I'll just want a alert to pop up first and then let the user type the name for the new row.
You have to identify each row somehow. One way is to use the index in the table as the identifier. I guess your adding the row to a NSArray which is mapped to the table rows or something similar, so you know the index of the new row. You only have to update the row of that index using this method on your UITableView:
- (UITableViewCell *)cellForRowAtIndexPath:(NSIndexPath *)indexPath
Assuming you have only one section, your array is called 'arrayWithRowsData' and you put the new row at the end, you can create the index path with:
int newRowIndex = [arrayWithRowsData count] - 1;
NSIndexPath* indexPath = [NSIndexPath indexPathForRow:newRowIndex inSection:0];
Hope it helps.
I'm trying to get a table layout as shown below working with view-based NSTableViews that have been introduced in Lion.
There were multiple approaches described for cell-based NSTableViews, e.g. Mimic the artwork column, but these don't really apply for view based table views.
The idea is that the table gets populated by an array of objects, in one (or more) column spanning rows indicating that objects share some data in common. numberOfRowsInTableView: returns to total number of items (19 in the case of the attached image).
Has anyone tried something like this?
Layout
I was able to do this by using two separate NSTableViews that have their NSScrollView's scrolling synchronized. To learn how to synchronize multiple scroll view's (with the exact subclass code) read Scroll View Programming Guide for Mac - Synchronizing Scroll Views
I have groupTableView that has a single column and shows the views that represent the group. I also have itemTableView that has columns representing the items of the group. I use the same delegate/datasource methods with if-else-statements to check which NSTableView is being used and respond accordingly with the proper # of rows, cell view, etc.. Additionally, I implement the following delegate method to adjust the group table view's row height to be equal the sum of the item row heights of the rows in the group:
- (CGFloat)tableView:(NSTableView *)tableView heightOfRow:(NSInteger)row
{
if (tableView == self.groupTableView) {
NSUInteger firstRowIndexForGroup = ...;
NSUInteger lastRowIndexForGroup = ...;
CGFloat groupHeight = 0.0;
for (NSUInteger currentRowIndex = firstRowIndexForGroup; currentRowIndex <= lastRowIndexForGroup; currentRowIndex++) {
groupHeight += [self.itemTableView rectOfRow:lastRowIndexForGroup].size.height;
}
return groupHeight - [self.itemTableView intercellSpacing].height;
} else {
return self.itemTableView.rowHeight;
}
}
You must also call -noteHeightOfRowsWithIndexesChanged: every time the table view needs a group view because the height changes according to the number of rows in the group.
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
if (tableView == self.groupTableView) {
GroupRowView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
// configure view
[tableView noteHeightOfRowsWithIndexesChanged:[NSIndexSet indexSetWithIndex:row]];
return view;
} else {
ItemRowView *view = [tableView makeViewWithIdentifier:tableColumn.identifier owner:self];
// configure view
return view;
}
}
I disabled row selection and horizontal and vertical scroll bars on the group table view. I also made the horizontal grid solid for both table views. Finally, I position the group table view directly next to the item table view with no gap in between so it appears as if it's simply another column in a single table view. The result is a flawless implementation that has zero lag between the table views. To the user, it appears as if it's a single table view.
Could you not use an NSOutlineView instead? It's specifically designed to have grouping support.
I have a NSTableView with multiple columns. clicking each of the columns sorts by the column like in iTunes. However when the tableview first loads the rows are unsorted and no tablecolumn is highlighted or displaying the up/down indicator image. I'm wondering if theres a simple way I can programmatically set the column the table is sorted by and set the indicator image on startup.
The only solution I can think of is using [NSTableView setIndicatorImage: inTableColumn:] and [NSTableView setHighlightedColumn:], but that makes it so that clicking on the header doesnt highlight the column. I would rather not have to use tableView:mouseDownInHeaderOfTableColumn: and rewrite the whole click on header to sort thing.
You might try setting your sort discriptor.
- (void)setSortDescriptors:(NSArray *)array
- (void)windowControllerDidLoadNib:(NSWindowController *) windowController
{
[super windowControllerDidLoadNib:windowController];
NSSortDescriptor* sortDescriptor = [[[NSSortDescriptor alloc] initWithKey: #"order" ascending: YES] autorelease];
[oTable setSortDescriptors:[NSArray arrayWithObject:sortDescriptor]];
}
http://lists.apple.com/archives/cocoa-dev/2006/May/msg01434.html