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
Related
I'm programmatically setting up a multi-column NSOutlineView. The first column contains only checkboxes whereas the other columns contain text. I'm creating the checkboxes like this:
cell = [[NSButtonCell alloc] init];
[cell setButtonType:NSSwitchButton];
[cell setImagePosition:NSImageOnly];
Now I want to adjust the width of the first NSTableColumn to the exact width required by a checkbox. To calculate the dimensions of a checkbox cell, I do the following:
NSCell *cell = [m_view preparedCellAtColumn:0 row:0];
unsigned cellWidth = [cell cellSize].width;
This returns 18 in cellWidth. This is probably the right value but it isn't sufficient because NSOutlineView always seems to insert some blank space before the cells of the very first column. Here's what it looks like:
As you can see the checkboxes are currently cut off because the column width is too small because of the blank space in front of the checkbox.
Therefore, here is my question: How can I calculate the width of this blank space for my first NSTableColumn so that I can calculate the full column width required to show the checkbox and blank space? Is there maybe also a way to get rid of this blank space?
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 have a View within an NSPopover, and I am unable to set the tab order correctly. I have set the nextKeyView within my 4 text fields. But it tends to flip from TextField1 to Search1, instead of TextField1 -> TextField2. I have tried inserting [self.view.window makeFirstResponder:textField1] also [self.view.window setInitialFirstResponder:textField1] along with recalculatekeyviewloop but with no luck.
Any help would be much appreciated.
I had a similiar problem when composing the popover-view of certain subviews programatically in awakeFromNIB. I could solve the problem by inserting the subviews after the popover had its private NSPopoverWindow set (i.e. it was shown the first time). It seems like the popover is re-evaluating the view-loop when the popover-view is embedded in the private child-window - ignoring the view-loop given in the view.
You could try the following:
-(void) popoverDidShow:(NSNotification *)notification{ // NSPopoverDelegate-method
if (!popoverDidShowForTheFirstTime){
[self setUpViews];
}...
-(void) setUpViews{
popoverDidShowForTheFirstTime = YES;
// insert views and establish nextKeyViews ...
I have an NSTableView with columns bound to an NSArrayController.
The table view shows a list of email messages:
Flag if unread
Subject
Attachment size
The user can click on the Attachment Size column to sort the list, but I would like the table to always be sorted by the "unread" flag first so that the unread messages always remain at the top of the list.
I did not bind the Array Controller's sort descriptors to anything, yet table sorting works magically by clicking on the table columns (why?). Is there some way I can intercept setting the Array Controller's sort descriptors and insert the "Unread" sort descriptor first?
Example of a table sorted by attachment size:
UNREAD▼ SUBJECT ATTACHMENT SIZE▼
------ ------- ------------------
yes Hello.. 110kb
yes Test... 90kb
no Foobar 200kb
no Hey 100kb
no Test2 10kb
Well, the reason it "just works" is because the table columns call setSortDescriptors: on their bound NSArrayController.
Assuming you want the table to remain sortable, but you always want to sort by "unread", this is how I would go about it:
First, subclass NSArrayController and override arrangeObjects:
- (NSArray *)arrangeObjects:(NSArray *)objects {
NSMutableArray *oldSorted = [[super arrangeObjects:objects] mutableCopy];
NSMutableArray *newSorted = [NSMutableArray arrayWithCapacity:[oldSorted count]];
for (id anObject in oldSorted)
if ([[anObject valueForKey:#"isUnread"] boolValue])
[newSorted addObject:anObject];
[oldSorted removeObjectsInArray:newSorted];
[newSorted addObjectsFromArray:oldSorted];
[oldSorted release];
return newSorted;
}
This puts unread messages at the "top" (beginning of array). I'm not sure this is the most efficient sorting algorithm, but I believe it's the correct way to go about it.
I think that you can just set an array of sortDescriptors on your array controller during awakeFromNib. No need to force arrangeObjects:, this functionality totally built in.
- (void)awakeFromNib {
[super awakeFromNib];
NSSortDescriptor *unreadSorter = [[NSSortDescriptor sortDescriptorWithKey:#"isUnread" ascending:NO)] autorelease];
NSArray *arrayOfSortDescriptors = [NSArray arrayWithObject:unreadSorter];
[self setSortDescriptors:arrayOfSortDescriptors];
}
The columns will still remain sortable when you click the column header.
So I admit to being a total noob to cocoa, so I offer a noob question. I'm probably just missing the dumb obvious somewhere but i just cant seem to get my table to populate data.
I'm following the table view playground example but everytime i try to mimic the Basic TableView Window the first row becomes the height of the number of rows i added (at least thats what it looks like. Here is my code:
- (id)tableView:(NSTableView *)tableView objectValueForTableColumn:(NSTableColumn *)tableColumn row:(int)row
{
NSString *identifier = [tableColumn identifier];
if ([identifier isEqualToString:#"filename"]) {
// We pass us as the owner so we can setup target/actions into this main controller object
NSTableCellView *cellView = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
// Then setup properties on the cellView based on the column
cellView.textField.stringValue = [fileList filenameAtIndex:row];
cellView.imageView.objectValue = [[NSWorkspace sharedWorkspace] iconForFile:[fileList fullPathAtIndex:row]];
return cellView;
}
else if ([identifier isEqualToString:#"path"]) {
NSTextField *textField = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
textField.objectValue = [fileList pathAtIndex:row];
return textField;
}
else if ([identifier isEqualToString:#"preview"]) {
NSTextField *textField = [fileBrowserTable makeViewWithIdentifier:identifier owner:self];
textField.objectValue = [fileList previewAtIndex:row];
return textField;
}
return nil;
}
I think its worth mentioning that when using a the old school text field cell, I have no problems displaying data (of course the above code is different in that case) so im positive sure its not a problem with my data structure that holds the values. I have also set the correct delegate and data source
The cell using the 'filename' identifier uses the 'image and text table view cell' while the others use just a 'text table cell view'. Neither of them work so i'm guessing something is wrong with how I set my table up. But when comparing my table with that of the example, it's just a spitting reflection (minus identifiers file names).
One thing that I notice that I can't quite figure out is that the example says:
The NSTableView has two reuse identifier assocations: "MainCell" and "SizeCell" are both associated with the nib ATBasicTableViewCells.xib
I don't really understand this statement. However that being said, the example doesn't contain any ATBasicTableViewCells.xib nor does it have any associations with it (code or ib) that I can find.
Have you tried to set the rowSizeStyle of the NSTableView to NSTableViewRowSizeStyleCustom?
[UPDATE] Re-reading your question, it's not clear for me what your problem is. The solution I have given is related to problems with the size of each cell which is not taken into account unless the rowSizeStyle is set to custom.