Ios error while sorting an NSArray - objective-c

When I try to sort an array, I got an exception like below:
*** Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[ valueForUndefinedKey:]: this class is not key value coding-compliant for the key levels.'
To sort the arrays I use the following lines:
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"levels" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reversedLevelIdArray = [levelsDictionary.allKeys sortedArrayUsingDescriptors:descriptors];
The levelsDictionary.allKeys contains the values like below:
( level2, level1 )
What is wrong with my code?

Using Sort Descriptor...
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"self" ascending:YES];
NSArray *descriptors = [NSArray arrayWithObject: descriptor];
NSArray *reversedLevelIdArray = [levelsDictionary.allKeys sortedArrayUsingDescriptors:descriptors];
NSLog(#"%#", reversedLevelIdArray);
You can use #selector to sort an array...
NSArray *resultArray = [levelsDictionary.allKeys sortedArrayUsingSelector:#selector(caseInsensitiveCompare:)];
Using Comparator....
NSArray *resultArray = [levelsDictionary.allKeys sortedArrayUsingComparator:^NSComparisonResult(id _Nonnull obj1, id _Nonnull obj2) {
return obj2 > obj1;
}];

Just use the following codes to sort the array, instead of all of your other line of codes..
NSArray *reversedIdArray = [levelsDictionary.allKeys sortedArrayUsingDescriptors:#selector(caseInsensitiveCompare:)];

You're sorting strings and they are ahving no property or method named levels. You should sort the values instead, like:
[levelsDictionary.allKeys sortedArrayUsingSelector:#selector(compare:)];

I have checked you code, you are sorting the data and accessing the wrong key name of dictionary.
As you said that your levelDictionary contains the keys name as "level2", "level1", etc....
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"levels" ascending:YES];
In this code you have used the key name as "levels" is wrong, because I think your dictionary "levelsDictionary" does not contains any key name as "levels".
Please try to use the proper key name and your error will resolve.

Related

Objective C custom array sorting algorithm error

I am sorting an array of custom winery objects by a name attribute.
wineryNames = [NSMutableArray arrayWithArray:[wineryNames sortedArrayUsingComparator:^(Winery *a, Winery *b){
return [a.getName compare:b.getName options:NSCaseInsensitiveSearch];
}]];
I am receiving an error on the return line and the log says 'unrecognized selector'. I have no idea why this isn't working.
I think this will do the job:
NSSortDescriptor *sortDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES
selector:#selector(caseInsensitiveCompare:)];
NSArray *sortedArray = [wineryNames sortedArrayUsingDescriptors:#[sortDescriptor]];
More info Here!

Accessing descriptors in array of arrays

I have a mutable array containing some arrays for use in a table view controller. The arrays contain a title and some other information. I want the arrays in the master array to be sorted alphabetically in terms of the title they contain. I have assigned the titles with keys:
NSString *title = #"objectTitle";
NSDictionary *dict = [NSDictionary dictionaryWithObjectsAndKeys:_storedTitle.text, title, nil];
NSArray *newArray = #[#"Login", dict, _storedUsername.text, _storedPassword.text];
I store the newArray in my masterArray and try to sort the array thus:
//sort array alphabetically
NSSortDescriptor *titleDescriptor = [[NSSortDescriptor alloc] initWithKey:#"objectTitle" ascending:YES];
NSArray *sortDescriptors = #[titleDescriptor];
NSArray *sortedArray = [_masterArray sortedArrayUsingDescriptors:sortDescriptors];
_masterArray = sortedArray.copy;
This is not working, as i have not specified the index where the titleDescriptor is stored. How do I do this?
When accessing the title at a given index (index) in the master array is done as follows:
NSLog(#"%#", [[[_masterArray objectAtIndex:index] objectAtIndex:1] objectForKey:#"objectTitle"]);
Modified your code like this:-
NSSortDescriptor *sortedDescriptor =
[[[NSSortDescriptor alloc]
initWithKey:#"objecttitle"
ascending:YES
selector:#selector(localizedCaseInsensitiveCompare:)] autorelease];
NSArray * descriptors =
[NSArray arrayWithObjects:sortedDescriptor, nil];
NSArray * sortedArray =
[array sortedArrayUsingDescriptors:descriptors];
NSlog(#"%#",sortedArray);

Sort NSArray of NSDictionaries

I have a problem with sorting... I need to sort NSArray containing NSDictionaries. As an order key I have to use element from the NSDictionary.
I was reading a little about sorting NSArray but it is not clear to me.
Could you try help me?
Use an NSSortDescriptor and a keypath. Assuming the key for the dictionary is key:
NSSortDescriptor *sd = [NSSortDescriptor sortDescriptorWithKey:#"key" ascending:YES];
NSArray *sorted = [array sortedArrayUsingDescriptors:[NSArray arrayWithObject:sd]];

Sort NSArray of custom objects by their NSDate properties

I am attempting to sort an NSArray that is populated with custom objects. Each object has a property startDateTime that is of type NSDate.
The following code results in an array, sortedEventArray, populated but not sorted. Am I going about this the completely wrong way or am I just missing something small?
NSSortDescriptor *dateDescriptor = [NSSortDescriptor sortDescriptorWithKey:#"startDateTime"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray sortedArrayUsingDescriptors:sortDescriptors];
Are you sure that the startDateTime instance variables of the node events are non-nil?
If you don't have one already, you might add a (custom) -description method to your node event objects that does something like this:
- (NSString *)description {
return [NSString stringWithFormat:#"%# - %#",
[super description], startDateTime]];
}
Then in your sorting code log the array before and after:
NSLog(#"nodeEventArray == %#", nodeEventArray);
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"startDateTime"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:dateDescriptor];
NSArray *sortedEventArray = [nodeEventArray
sortedArrayUsingDescriptors:sortDescriptors];
NSLog(#"sortedEventArray == %#", sortedEventArray);
If the startDateTime's are all nil, then the before and after arrays will have the same order (since the sorting operation will equate to sending all the -compare: messages to nil, which basically does nothing).
Did you try by specifying the NSDate comparator?
Eg:
NSSortDescriptor *dateDescriptor = [NSSortDescriptor
sortDescriptorWithKey:#"startDateTime"
ascending:YES
selector:#selector(compare:)];
This should enforce the usage of the correct comparator of the NSDate class.
Ok, I know this is a little late, but this is how I would do it:
NSArray *sortedEventArray = [events sortedArrayUsingComparator:^NSComparisonResult(Event *event1, Event *event2) {
return [event1.startDateTime compare:event2.startDateTime];
}];
Obviously, replace Event with the class of your custom object. The advantage of this approach is that you are protected against future refactoring. If you were to refactor and rename the startDateTime property to something else, Xcode probably would not change the string you're passing into the sort descriptor. Suddenly, your sorting code would break/do nothing.
You can achieve like this,
NSSortDescriptor *descriptor = [[NSSortDescriptor alloc] initWithKey:#"anyDateField" ascending:YES];
NSMutableArray *arr = [[array sortedArrayUsingDescriptors:[NSArray arrayWithObjects:descriptor,nil]]mutableCopy];
You can achieve this like this,
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"date" ascending:FALSE];
[self.Array sortUsingDescriptors:[NSArray arrayWithObject:sortDescriptor]];

How to sort an array which contains Dictionaries?

I have an array which contains dictionaries in it; so how can I sort the array according to dictionary key values?
If every element in the array is a dictionary containing a certain key, you can sort the array using a sort descriptor. For instance, if every element is a dictionary containing a key called "name":
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"name"
ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSArray *sortedArray = [array sortedArrayUsingDescriptors:sortDescriptors];
The other way to achieve this would be using sortedArrayUsingComparator: method
NSArray *sortedArray = [array sortedArrayUsingComparator:^NSComparisonResult(id obj1, id obj2) {
return [[obj1 valueForKey:#"value"] compare:[obj2 valueForKey:#"value"]];
}];
why don't you use a sorted dictionary where the property of sorted elements comes already with the data structure?
Please do check it out here
Hope this helps.
The above shared answer by Bavarious helped me.Just want to add one more thing.If you want to sort a mutable array use something like the below code
NSSortDescriptor *sortByName = [NSSortDescriptor sortDescriptorWithKey:#"name" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortByName];
NSMutableArray *sortedArray = [[NSMutableArray sortedArrayUsingDescriptors:sortDescriptors]mutableCopy];
let arrDescriptor = NSSortDescriptor(key: "order", ascending: true)
let sortDescriptors: NSArray = [arrDescriptor]
let sortedArray = instancesubArray.sortedArray(using: sortDescriptors as [AnyObject] as [AnyObject] as! [NSSortDescriptor])
print(sortedArray)