iOS Reverse tableView sort order - iphone

Is there a way to reverse the tableView order?
For example, I have a tableView that sorts by firstUpdated to LastUpdated. It does automatically cause its composed by plist data. But what if I want to put the newest data on top and the older on bottom?

The other solution will work fine but this one is a bit shorter.
NSArray *reversedArray = [[originalArray reverseObjectEnumerator] allObjects];

You should sort the array you use to populate the table view.
The other two answers would work, but I have another way of doing this if you need to sort by any property of the object:
You can create a method -sortMyArray
and it will look like:
-(void)sortMyArray
{
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"SomeObjectSortProperty" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[MyArray sortUsingDescriptors:sortDescriptors];
[sortDescriptor release];
}
and of course, every time after you call this method, you need to call your table view reload data method.
Hope this helps.

Another alternative (to maintain only a copy of the original array), is to use the original array and just grab objects in backwards order in the UITableViewDataSource functions.
Example:
id currentObject = [originalArray objectAtIndex:(originalArray.count - indexPath.row - 1)];
This is actually probably a better solution because you don't need to maintain 2 copies of the same data simply for reversed order.

You were using the array to populate the data in table view ...
Sort that array rather than sorting the table order..

self.yourCurrentArrayOfObjects = ...;
NSMutableArray *reversedArray = [NSMutableArray arrayWithCapacity:yourCurrentArrayOfObjects.count];
for (id object in yourCurrentArrayOfObjects.reverseObjectEnumerator)
{
[reversedArray addObject:object];
}
self.yourCurrentArrayOfObjects = [reversedArray copy];
[self.tableView reloadData];

Related

Sort an NSMutableArray / Dictionary with several objects

I am having a problem that I think I am overcomplicating.
I need to make either an NSMutableArray or NSMutableDictionary. I am going to be adding at least two objects like below:
NSMutableArray *results = [[NSMutableArray alloc] init];
[results addObject: [[NSMutableArray alloc] initWithObjects: [NSNumber numberWithInteger:myValue01], #"valueLabel01", nil]];
This gives me the array I need but after all the objects are added I need to be able to sort the array by the first column (the integers - myValues). I know how to sort when there is a key, but I am not sure how to add a key or if there is another way to sort the array.
I may be adding more objects to the array later on.
Quick reference to another great answer for this question:
How to sort NSMutableArray using sortedArrayUsingDescriptors?
NSSortDescriptors can be your best friend in these situations :)
What you have done here is create a list with two elements: [NSNumber numberWithInteger:myValue01] and #"valueLabel01". It seems to me that you wanted to keep records, each with a number and a string? You should first make a class that will contain the number and the string, and then think about sorting.
Doesn't the sortedArrayUsingComparator: method work for you? Something like:
- (NSArray *)sortedArray {
return [results sortedArrayUsingComparator:(NSComparator)^(id obj1, id obj2)
{
NSNumber *number1 = [obj1 objectAtIndex:0];
NSNumber *number2 = [obj2 objectAtIndex:0];
return [number1 compare:number2]; }];
}

How to sort NSArray of objects based on one attribute

I am trying to sort an array of managed objects alphabetically. The attribue that they need to be sorted by is the name of the object (NSString) with is one of the managed attributes. Currently I am putting all of the names in an array of strings and then using sortedNameArray = [sortedNameArray sortedArrayUsingSelector:#selector(localizedCaseInsensitiveCompare:)]; and then enumerating them back into an array with the objects. This falls apart when two names are the same so I really need to be able to sort by one attribute. How should I go about doing this?
Use NSSortDescriptor. Just search the documentation on it and there some very simple examples you can copy right over. Here is a simplified example:
NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc] initWithKey:#"MyStringVariableName" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject:valueDescriptor];
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:descriptors];
And just like that you have a sorted array.
You can do this by using NSSortDescriptor,
eg.
`NSSortDescriptor *valueDescriptor = [[NSSortDescriptor alloc]initWithKey:#"distance" ascending:YES];`
// Here I am sorting on behalf of distance. You should write your own key.
NSArray * descriptors = [NSArray arrayWithObject:valueDescriptor];
NSArray *sortedArray=[yourArray sortedArrayUsingDescriptors:descriptors];`

Variable Scope issue

It may be because this has been a long day... but I am having with some basic scope issues. I am creating an object, passing it in to a delegate method, and adding it to an array wihin the method.
When I check the value of device within the method, it contains the device information.
Here is the code for the delegate function in the class that registered the delegate:
- (void) newAmeriscanDevice:(AmeriscanDevice *)device {
if (!self.deviceArray)
self.deviceArray = [[NSMutableArray alloc] init];
// add the newly created device...
[self.deviceArray addObject:device];
}
This method is within the same class of the earlier function. The deviceArray shows that it contains one object (supposed to the the driver object from above). When I look at the value of the device object in here, it is always 0x0.
- (void) endDevices:(NSNumber *)numberOfDevices {
// get out of here is there is no device in the device array
if (!self.deviceArray)
return;
// lets sort the array by order of the devices sort order
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"sortOrder" ascending:YES];
NSArray *sortDescriptorArray = [NSArray arrayWithObject:sortDescriptor];
// the array should now be sorted correctly...
[self.deviceArray sortUsingDescriptors:sortDescriptorArray];
// we now have data -- so.... lets reload the table
[self.tableView reloadData];
}
So.... any idea on how to make sure the object in the array retains its values?
Thanks All
Mike
write code some thing like this
- (void) newAmeriscanDevice:(AmeriscanDevice *)device {
if (!self.deviceArray)
{
NSMutableArray *tempArray= [[NSMutableArray alloc] init];
self.deviceArray=tempArray;
[tempArray release];
}
[self.deviceArray addObject:device];
}
And check some where you are releasing the array or any reference which having the same location(any other array you have released in which you copy the array by using '=' operator).release it in dealloc.
I made a mistake with my assessment. I was looking at the debugger values when hovering over the array. It would show that there was one object and the object pointer was 0x0. I changed the code:
- (void) endDevices:(NSNumber *)numberOfDevices {
// get out of here is there is no device in the device array
if (!self.deviceArray)
return;
NSLog(#"Array Count: %i", [self.deviceArray count]);
for (id object in self.deviceArray) {
if (object == nil) {
NSLog(#"Nil Object");
} else {
AmeriscanDevice *dev = (AmeriscanDevice *)object;
NSLog(#"Device: %#", [dev description]);
}
}
// lets sort the array by order of the devices sort order
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"sortOrder" ascending:YES];
NSArray *sortDescriptorArray = [NSArray arrayWithObject:sortDescriptor];
// the array should now be sorted correctly...
[self.deviceArray sortUsingDescriptors:sortDescriptorArray];
// we now have data -- so.... lets reload the table
[self.tableView reloadData];
}
Once I changed this code, it showed that the object in the array was in face the proper type object.
My problem was in the display of a table. Apparently the cellForRowAtIndexPath method is not being called in the table when I called the reloadData or when the view is first shown. I created this table view using xcode 4, so I am heading into the xib file to see whats not linked :)

How can i get Original order of NSDictionary/NSMutableDictionary?

i have created NSMutableDictionary with 10 keys.Now i want to access NSMutableDictionary keys in a same order as it was added to NSMutableDictionary (using SetValue:* forKey:* );
How can i achieve that ?
If you absolutely must use a dictionary container, you have to use a key that is sortable by the order in which you add key-value pairs. Thus, when creating your dictionary, you use a key that is an auto-incrementing integer or similar. You can then sort on the (integer) keys and retrieve the values associated with those keys.
If you do all of that, however, you may as well just use an NSMutableArray and add values to the array directly! It will be much faster and require less code. You just retrieve objects in order:
for (id obj in myArray) { /* do stuff with obj... */ }
NSMutableDictionary can't do that. Take a look at e.g. Matt Gallaghers OrderedDictionary.
I wrote a quick method to take a source array (of objects that are all out of order) and a reference array (that has objects in a desired (and totally arbitrary) order), and returns an array where the items of the source array have been reorganized to match the reference array.
- (NSArray *) reorderArray:(NSArray *)sourceArray toArray:(NSArray *)referenceArray
{
NSMutableArray *returnArray = [[NSMutableArray alloc] init];
for (int i = 0; i < [referenceArray count]; i++)
{
if ([sourceArray containsObject:[referenceArray objectAtIndex:i]])
{
[returnArray addObject:[arrReference objectAtIndex:i]];
}
}
return [returnArray copy];
}
Note that this is very fragile. It uses NSArray's containsObject: method, which ultimately will call NSObject's isEqual:. Basically, it should work great for arrays of NSStrings, NSNumbers, and maybe NSDates (haven't tried that one yet), but outside of that, YMMV. I imagine if you tried to pass arrays of UITableViewCells or some other really complex object, it would totally sh*t itself, and either crash or return total garbage. Likewise if you were to do something like pass an array of NSDates as the reference array and an array of NSStrings as the source array. Also, if the source array contains items not covered in the reference array, they'll just get discarded. One could address some of these issues by adding a little extra code.
All that said, if you're trying to do something simple, it should work nicely. In your case, you could build up the reference array as you are looping through your setValue:forKey:.
NSMutableArray *referenceArray = [[NSMutableArray alloc] init];
NSMutableDictionary *yourDictionary = [[ NSMutableDictionary alloc] init];
for (//whatever you are looping through here)
{
[yourDictionary setValue://whatever forKey:key];
[referenceArray addObject:key];
}
Then, when you want to loop over your items in the order they came in, you just
for (NSString *key in [self reorderArray:[myDict allKeys] toArray:referenceArray])
Actually you have a reference array in order manner then why you have to add to one more array.So i guess this approach is not good.Please consider my opinion.
Although #GenralMike 's answer works a breeze, it could be optimized by leaving off the unnecessary code as follows:
1) Keep an array to hold reference to the dictionary keys in the order they are added.
NSMutableArray *referenceArray = [[NSMutableArray alloc] init];
NSMutableDictionary *yourDictionary = [[ NSMutableDictionary alloc] init];
for (id object in someArray) {
[yourDictionary setObject:object forKey:someKey];
[referenceArray addObject:someKey]; // add key to reference array
}
2) Now the "referenceArray" holds all of the keys in order, So you can retrieve objects from your dictionary in the same order as they were originally added to the dictionary.
for (NSString *key in referenceArray){
//get object from dictionary in order
id object = [yourDictionary objectForKey:key];
}

iPhone - Merge keys in a NSArray (Objective-C)

I'm having troubles with arrays and keys... I have an array from my database:
NSArray *elementArray = [[[menuArray valueForKey:#"meals"] valueForKey:#"recipe"] valueForKey:#"elements"]
The problem here is that I would like all my elements of all my meals of all my menus in an array such that:
[elementArray objectAtIndex:0] = my first element
etc...
In the example above, the elements are separated by the keys.
How can I get that?
Hope it's clear enough...
Thanks
From your code snippet, it is not clear to me exactly how your data is structured, but I think it's analogous to having an NSDictionary (called aDictionary) of NSArray and wanting to combine all the NSArray into one. If this is the case, then:
NSMutableArray *resultArray = [[[NSMutableArray alloc] init] autorelease];
for (id dictionaryKey in aDictionary) {
[resultArray addObjectsFromArray:[aDictionary objectForKey:dictionaryKey]];
}
return [NSArray arrayWithArray:resultArray];
(This code has not been tested.)