Multiple sort on Array for UITableView - uitableview

I have an array of categories returned from a parse.com query (sorted ascending) that are listed in a TableView.
I want to place a category called "Everything" at the top of the list and then sort the rest of the list ASC. I'm thinking I should use NSDescriptor, NSComparator or NSPredicate but wanted to get some feedback on the best route.
Another angle I thought might work is to extract "Everything" out of the array and put it in a string and then use 2 custom cells and put "Everything" on top.
Any advice on which option would be best? Or is there another route I missed?

I solved this by copying the results Array into a mutable Array and then sorted the Array.
NSMutableArray *sort = [[NSMutableArray alloc] initWithArray:self.objects];
id tmp=[sort objectAtIndex:6];
[sort removeObjectAtIndex:6];
[sort insertObject:tmp atIndex:0];

Related

Capture default sorting in NSMutableArray?

I have an NSMutableArray which contain objects retrieved from CloudKit. Initially, I'm not doing any sorting so it's using whatever sorting order the records are retrieved. There are some user interactions where I would then need to sort it for specific purposes. However, I want to be able to undo that sorting and go back to the default order. But since the initial sorting is not specified by me, I'm wondering if there is a way capture that initial sorting order? I looked at the documentation for NSMutableArray and NSSortDescriptor and didn't see any sort of methods that I could call to do that. Is there a built in way that I'm missing or does anyone have a custom way of doing this?
Thanks!
AFAIK, NSArray (and therefore NSMutableArray) don't have any special default sorting. Their order is simply the order objects were added in the first place.
NSArray *arr1 = #[#1, #2, #3];
NSLog(#"%#", arr1); // (1, 2, 3)
NSArray *arr2 = #[#3, #1, #2];
NSLog(#"%#", arr2); // (3, 1, 2)
One solution to your problem is to store the initial array, and when the user wants to sort it, you copy the initial array, sort it and display it to the user, while keeping the original around. If the user wants to undo that, you just display the original array and get rid of the sorted copy.
Here is very basic pseudo-code:
NSMutableArray *originalArray = [self arrayFromCloudKit]; // fetch from CloudKit
// now the user wants it sorted alphabetically
NSMutableArray *alphabeticallySorted = originalArray.mutableCopy
[alphabeticallySortedsortUsingSelector:#selector(localizedCaseInsensitiveCompare:)];
[self storeOriginalArray:originalArray];
[self displayUIWithArray:alphabeticallySorted];
// but if the user changes their mind, you just fetch the original and delete the sorted
NSMutableArray *originalArray = [self getOriginalArray];
[self displayUIWithArray:originalArray];

Filter array dynamically based off 3 NSPredicates

I have a NSMutableArray of NSDictionaries. I would like to be able to filter dynamically.
For example, I have 3 types of filters
- area
- item
- type
if area is chossen then I would like to filter the Array with the area predicate, However if the user then chooses to filter item too, the currently filtered area array will then have the item filter applied too it.
However if the area filter is removed then I would like to show the new item filter.
It gets even more complicated when type is introduced, however I am struggling to get this to work correctly and don't really know where to start with the logic of it.
I can get the array to filter based off the last selected predicate. So if I choose area then items the current filter will only be items not both.
Try something like:
NSMutableArray *predicates = [NSMutableArray array];
if (...) {
[predicates addObject:...];
}
NSCompoundPredicate *p = [[NSCompoundPredicate alloc] initWithType:NSAndPredicateType subpredicates:predicates];
Where you add the individual predicates to the array if they are required. This is assuming that at least one predicate does need to be applied.

insertNewObjectForEntityForName at first position in the table not last

How to insert the record with coredata at first position in table? currently if i add insertNewObjectForEntityForName it adds record to last.
Well, as far as i know this is not possible. However one thing you could do is manipulate how the objects are retrieved from the DB. For example, for such requirements it is often useful to have an NSDate property in your model class. While inserting objects into the DB, pass [NSDate date] for this property. And while pulling out objects from the DB, write a sorting algorithm which returns the records sorted by the Date of insertion
In your model class' header file
Header.h
//Declare this property
NSDate *dateOfInsertion
//This method returns objects sorted by DateOf Insertion
- (NSArray*)arraySortedByDateOfInsertion {
NSSortDescriptor *descriptor = [NSSortDescriptor sortDescriptorWithKey:#"dateOfInsertion" ascending:NO];
return [self sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];
}
Hope this helps
You cannot decide where to add element in the table. But you use array for this . You can add the element at the top of the array so it will appeared as a first row in the table :
- (void)insertObject:(id)anObject atIndex:(NSUInteger)index

iOS filtering an array

I have an array of data that is displayed in a table. The array has multiple fields, including two specific ones I want to filter, the "call type" and the "county". The value for "call type" is either an "f" or "e" and the value for the county is either "w" or "c". I want to have 4 UISwitch's to to either turn on/off the "w", turn on/off the "c" etc. Its hard to explain but if you go to this website and look at the top right corner, its exactly what I want to do. http://www.wccca.com/PITS/ Out of the 4 filters, two filters control the county field, and two filters control the call type field. but they all operate independently. How would I go about accomplishing this? Would I use NSPredicate to create a new array each time something is filtered or what? Thanks.
You could definitely use an NSPredicate for this. Probably the easiest thing to do would be to use the same IBAction for all four switches and have it do a recalculation:
- (IBAction)anySwitchDidChange:(id)sender
{
// make a set of all acceptable call types
NSMutableSet *acceptableCallTypes = [NSMutableSet set];
if(self.fSwitch.on) [acceptableCallTypes addObject:#"f"];
// ... etc, to create acceptableCallTypes and acceptableCounties
NSPredicate *predicate =
[NSPredicate predicateWithFormat:
#"(%# contains callType) and (%# contains county)",
acceptableCallTypes, acceptableCounties];
/*
this predicate assumes your objects have the properties 'callType' and
'county', and that you've filled the relevant sets with objects that would
match those properties via isEqual:, whether strings or numbers or
anything else.
NSDictionaries are acceptable since the internal mechanism used here is
key-value coding.
*/
NSArray *filteredArray = [_sourceArray filteredArrayUsingPredicate:predicate];
// send filteredArray to wherever it needs to go
}
Using predicateWithFormat: causes the text to be parsed right there and then. In this case that should be no problem whatsoever but in general you can create the predicates in advance and supply only the parameters at the relevant moment, should you ever end up using one in a really time critical area.

Sort multiple arrays

Here is my situation:
I manipulate 6 NSMutableArrays. One of them has NSDates objects in it, the other ones have NSNumbers. When I populate them, I use addObject: for each of them, so index 0 of each array contains all the values I want for my date at index 0 in the dates array.
I want to make sure that the arrays are all sorted according to the dates array (order by date, ascending), meaning that during the sorting, if row 5 of the dates array is moved to row 1, it has to be applied to all the other arrays as well.
I was previously using CoreData, but I must not use it anymore (please don't ask why, this is off-topic ;) ). In CoreData, I could use an NSSortDescriptor, but I have no idea on how to do it with multiple NSArrays...
As always, hints/answers/solutions are always appreciated :)
This is a common problem. Use the following approach.
Encapsulate your six arrays into an object - every instance will have six properties.
Implement compare: method on this object, using [NSDate compare:] (this step can be skipped but it's cleaner this way).
Now you have only one array - sort it using the method from step 2.
I think the better solution for you to have NSArray of NSDictionary objects.
NSArray *allValues = [[NSArray alloc] init];
NSDictionary *dict = #{"Date" : [NSDate date], #"Key1" : #"Value1", #"Key2" : #"Value2"};
Then you can sort this array with sortDescriptor without any problems.
And then you can also use Comparator or Sort Desriptor as you wish.
Wrap all your items that you are storing in an array into a single object. Each one of your previous 6 arrays will be a property.
Inside that object you can implement
- (NSComparisonResult)compare:(YourClass *)otherObject {
return [self.date compare:otherObject.date];
}
You can now sort the array and they will sort by date.

Resources