Sort NSArray with custom objects - objective-c

In my Xcode project I have the following classes:
Address
#interface LDAddress : NSObject{
NSString *street;
NSString *zip;
NSString *city;
float latitude;
float longitude;
}
#property (nonatomic, retain) NSString *street;
#property (nonatomic, retain) NSString *zip;
#property (nonatomic, retain) NSString *city;
#property (readwrite, assign, nonatomic) float latitude;
#property (readwrite, assign, nonatomic) float longitude;
#end
Location
#interface LDLocation : NSObject{
int locationId;
NSString *name;
LDAddress *address;
}
#property (readwrite, assign, nonatomic) int locationId;
#property (nonatomic, retain) LDAddress *address;
#property (nonatomic, retain) NSString *name;
#end
In an subclass of UITableViewController, there is a NSArray containing a lot of unsorted objects of LDLocations. Now, I want to sort the NSArray's objects ascending based on the property city of a LDAddress.
How can I sort the array using NSSortDescriptor?
I tried the following, but the app dumps when sorting the array.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Address.city" ascending:YES];
[_locations sortedArrayUsingDescriptors:#[sortDescriptor]];

Try making the first key lowercase.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"address.city" ascending:YES];

You can also sort an array with blocks:
NSArray *sortedLocations = [_locations sortedArrayUsingComparator: ^(LDAddress *a1, LDAddress *a2) {
return [a1.city compare:a2.city];
}];

This will allow to sort with multiple types. Like we need to sort the Movie based on time and if the time is equal then need to sort by name.
NSArray *sortedArray = [childrenArray sortedArrayUsingComparator:^NSComparisonResult(id a, id b) {
NSNumber *first = [NSNumber numberWithLong:[(Movie*)a timeInMillis]];
NSNumber *second = [NSNumber numberWithLong:[(Movie*)b timeInMillis]];
NSComparisonResult result = [first compare:second];
if(result == NSOrderedSame){
result = [((NSString*)[(Movie*)a name] ) compare:((NSString*)[(Movie*)b name])];
}
return result;
}];

-(NSArray*)sortedWidgetList:(NSArray*)widgetList
{
NSSortDescriptor *firstDescriptor = [[NSSortDescriptor alloc] initWithKey:#"itemNum" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObjects:firstDescriptor, nil];
NSArray *sortedArray = [widgetList sortedArrayUsingDescriptors:sortDescriptors];
return sortedArray;
}

Related

Is there a way to rearrange the contents of a list of arrays?

Is there a way to rearrange an array of objects such that the contents are rearranged such that all the xth elements are grouped in another array? I'm not sure the best way to explain this so I'll illustrate with an example:
theArray has 5 properties: number, color, size, height, quality. There are 50 instances of this array, each with different properties.
I want to rearrange this so there are 5 arrays with 50 items inside each array.
The way I would do it is:
NSMutableArray *innerTemp = [[NSMutableArray alloc] initWithCapacity:49];
NSMutableArray *outerTemp = [[NSMutableArray alloc] initWithCapacity:4];
for (int i = 0 ; i < [theArray count]; i++){
[innerTemp addObject:[[theArray objectAtIndex:i] number]];
[innerTemp addObject:[[theArray objectAtIndex:i] color]];
[innerTemp addObject:[[theArray objectAtIndex:i] height]];
[innerTemp addObject:[[theArray objectAtIndex:i] age]];
[innerTemp addObject:[[theArray objectAtIndex:i] quality]];
[outerTemp addObject:temp];
}
So I guess my question is, is there some easier way/more efficient to do this?
Just use KVC (Key Value Coding):
Assuming your class looks something like this:
#interface InstanceClass : NSObject
// IIRC properties need to be objects (hence the NSValue around NSSize), there is no auto-wrapping.
#property (readwrite, strong, nonatomic) NSNumber *number;
#property (readwrite, strong, nonatomic) NSColor *color;
#property (readwrite, strong, nonatomic) NSValue *sizeValue;
#property (readwrite, strong, nonatomic) NSNumber *height;
#property (readwrite, strong, nonatomic) NSNumber *quality;
#end
and you have an array like
NSArray *instances = #[instance1, instance2, instance3, instance4, ...];
then this would be all you need:
NSArray *numbers = [instances valueForKey:#"number"]; // array of numbers.
NSArray *colors = [instances valueForKey:#"color"]; // array of colors.
NSArray *sizes = [instances valueForKey:#"size"]; // array of sizes.
NSArray *heights = [instances valueForKey:#"height"]; // array of heights.
NSArray *qualities = [instances valueForKey:#"quality"]; // array of qualities.
This will do the trick.
Assuming your items in the instances array are numbered from 1..n a call to [instances valueForKey:#"number"] would then return an NSArray like #[#1, #2, #3, #4, ...].

Create an NSDictionary containing several NSArrays

I want to unite several NSArrays into one NSDictionary.
Here are my arrays:
#property (nonatomic, strong) NSArray *EuropeTable;
#property (nonatomic, strong) NSArray *AsiaTable;
#property (nonatomic, strong) NSArray *AfricaTable;
#property (nonatomic, strong) NSArray *LatinAmericaTable;
#property (nonatomic, strong) NSArray *NorthAmericaTable;
Any ideas on how to do this?
*EDIT
I want each array to have the same key #"country", so that I could use this single key later
NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
[dictionary setObject:self.EuropeTable forKey:#"EuropeTable"];
[dictionary setObject:self.AsiaTable forKey:#"AsiaTable"];
[dictionary setObject:self.AfricaTable forKey:#"AfricaTable"];
[dictionary setObject:self.LatinAmericaTable forKey:#"LatinAmericaTable"];
[dictionary setObject:self.NorthAmericaTable forKey:#"NorthAmericaTable"];
Then to access one of the arrays you need to:
NSArray *europeTable = [dictionary objectForKey:#"EuropeTable"];
UPDATE:
NSArray *array = [NSArray arrayWithObjects:self.EuropeTable,
self.AsiaTable,
self.AfricaTable,
self.LatinAmericaTable,
self.NorthAmericaTable, nil];
NSDictionary *dict = [NSDictionary dictionaryWithObject:array forKey:#"country"];
NSDictionary *countries =
[NSDictionary dictionaryWithObjectsAndKeys:
EuropeTable, #"You",
AsiaTable, #"Need To",
AfricaTable, #"Provide",
LatinAmericaTable #"More",
NorthAmericaTable, #"Details",
nil];
Without more details, I'm not sure any answer will help you much :)
NSMutableDictionary dict = [NSMutableDictionary dictionary];
[dict addObject:self.EuropeTable forKey:#"EuropeTable"];
etc...

How do I alphabetically sort a custom object field within a NSMutable Array?

I have a custom object like:
#import <Foundation/Foundation.h>
#interface Store : NSObject{
NSString *name;
NSString *address;
}
#property (nonatomic, retain) NSString *name;
#property (nonatomic, retain) NSString *address;
#end
I have an array of NSMutableArray (storeArray) containing Store objects:
store1 = [[Store alloc] init];
store1.name = #"Walmart";
store1.address = #"walmart address here..";
store2 = [[Store alloc] init];
store2.name = #"Target";
store2.address = #"Target address here..";
store3 = [[Store alloc] init];
store3.name = #"Apple Store";
store3.address = #"Apple store address here..";
//add stores to array
storeArray = [[NSMutableArray alloc] init];
[storeArray addObject:store1];
[storeArray addObject:store2];
[storeArray addObject:store3];
My question is how can I sort the array by the store name? I know I can sort an array alphabetically by using this line:
[nameOfArray sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
How can I apply this to the store name of my Store class?
NSSortDescriptor *sortDescriptor =
[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(caseInsensitiveCompare:)];
[nameOfArray sortedArrayUsingDescriptors:#[sortDescriptor]];
Related documentation:
[NSArray sortedArrayUsingDescriptors:]
NSSortDescriptor
Regexident's answer is based on NSArrays, the corresponding in-place sorting for NSMutableArray would be -sortUsingDescriptors:
[storeArray sortUsingDescriptors:
[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(caseInsensitiveCompare:)]]];
Now storeArray it-self will be sorted.

ObjectiveC, creating array of classes

I have a class that contains values:
#interface Params : NSObject {
[...]
NSString *fc;
NSString *sp;
NSString *x;
NSString *y;
[...]
#property (nonatomic, assign) NSString *fc;
#property (nonatomic, assign) NSString *sp;
#property (nonatomic, assign) NSString *x;
#property (nonatomic, assign) NSString *y;
[...]
#end
it's possible to create in objective-c an array of classes? like c# / java?
MyClass[] a = new MyClass[20] ???
a[0].fc = "asd" ?
or something equivalent?
thanks,
alberto
While the standard way to do this would be with an NSArray, you can do this with a C-style array as well:
int numObjects = 42;
Params ** params = malloc(sizeof(Param*) * numObjects);
for (int i = 0; i < numObjects; ++i) {
params[i] = [[[Params alloc] init] autorelease];
}
free(params);
However, using an NSArray would be much simpler. :)
You would use a standard NSArray to do this, in my example I have used views, but you can use pointers to any object.
UIView * object = [[UIView alloc] init];
UIView * object2 = [[UIView alloc] init];
UIView * object3 = [[UIView alloc] init];
NSArray * array = [[NSArray alloc] initWithObjects:object,object2,object3,nil];
[object release];[object2 release];[object3 release];//edit
UIView * test = [array objectAtIndex:0];
test.tag = 1337;

Can't release object

I can't release this object and I don't know why:
SchedVO *tmpSched;
tmpSched = [SchedVO alloc];
NSString *timeStr;
timeStr = [[node attributeForName:#"timestamp"] stringValue];
tmpSched.date = [NSDate dateWithTimeIntervalSince1970:timeStr.intValue];
tmpSched.uid = [node stringValue];
[playListArr addObject:tmpSched];
[tmpSched release];
sched:
#interface SchedVO : NSObject
{
NSDate *date;
NSString *uid;
}
#property (nonatomic,retain) NSDate *date;
#property (nonatomic,retain) NSString *uid;
#end
I think its somehow the nsdate part. Can someone help me out?
I believe you're missing an init. tmpSched = [[SchedVO alloc] init]; Init increments the Retain count to 1. You can't release something that hasn't been initialized.