I am developing a macOS Application in Objective-C. I would like to add as a feature the option to sort a NSTableView to show the selected items before the others. My code is:
NSUInteger idx = [self.itemsTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.items[idx]];
// get the next index in the set
idx = [self.itemsTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
self.items = [self.unFilteredItems sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
BOOL obj1Exists = [selectedObjects containsObject:obj1];
BOOL obj2Exists = [selectedObjects containsObject:obj2];
if (obj1Exists && !obj2Exists) {
return NSOrderedAscending;
}
if (obj1Exists && obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && !obj2Exists) {
return NSOrderedSame;
}
if (!obj1Exists && obj2Exists) {
return NSOrderedDescending;
}
return NSOrderedSame;
}];
[self.itemsTableView reloadData];
Unfortunately, on about 70.000 items and a selection of 4500 items, the comparator takes too much time. Can anybody point to me an alternate solution to the problem ? Thanks for any help.
Edit:
I have now tried another solution which proves to be faster but still not fast enough:
NSUInteger idx = [self.myMessagesTableView.selectedRowIndexes firstIndex];
NSMutableArray *selectedObjects = [NSMutableArray new];
while (idx != NSNotFound)
{
// do work with "idx"
// NSLog (@"The current index is %lu", (unsigned long)idx);
[selectedObjects addObject:self.myMessages[idx]];
// get the next index in the set
idx = [self.myMessagesTableView.selectedRowIndexes indexGreaterThanIndex:idx];
}
NSMutableArray *unselectedObjects = [NSMutableArray new];
[self.unFilteredItems enumerateObjectsUsingBlock:^(id _Nonnull obj, NSUInteger idx, BOOL * _Nonnull stop) {
if (![selectedObjects containsObject:obj]) {
[unselectedObjects addObject:obj];
}
}];
self.items = selectedObjects;
self.items = [self.items arrayByAddingObjectsFromArray:unselectedObjects];
[self.itemsTableView reloadData];
I hope somebody can point me in the right direction, probably trying to use selection indexes instead of an array of selected objects. Thanks again.
How about getting the selected objects and appending the unselected objects
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
// invert selectedRowIndexes
NSMutableIndexSet *invertedSelection = [NSMutableIndexSet indexSetWithIndexesInRange:NSMakeRange(0, self.items.count)];
[invertedSelection removeIndexes:self.itemsTableView.selectedRowIndexes];
NSArray *unselectedObjects = [self.items objectsAtIndexes:invertedSelection];
self.items = [selectedObjects arrayByAddingObjectsFromArray:unselectedObjects];
self.itemsTableView.selectedRowIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)];
[self.itemsTableView reloadData];
Or removing the selected objects and inserting them at the top
NSMutableArray *mutableItems = [self.items mutableCopy];
NSArray *selectedObjects = [self.items objectsAtIndexes:self.itemsTableView.selectedRowIndexes];
[mutableItems removeObjectsAtIndexes:self.itemsTableView.selectedRowIndexes];
NSindexSet *selectedIndexes = [NSIndexSet indexSetWithIndexesInRange:NSMakeRange(0, selectedObjects.count)]
[mutableItems insertObjects:selectedObjects atIndexes:selectedIndexes];
self.items = [mutableItems copy];
self.itemsTableView.selectedRowIndexes = selectedIndexes;
[self.itemsTableView reloadData];
I didn't test this.