I am trying to sort an NSMutableArray with the following structure:
(
{
Code = "390954-150";
Size = "35";
},
{
Code = 790540MSO;
Size = "30";
}
)
I am trying to sort basing on the Code value, the NSMutableArray is called arrayProduct:
//Sort array by Code
NSSortDescriptor *aSortDescriptor = [[NSSortDescriptor alloc] initWithKey:#"Code" ascending:YES];
[arrayProduct sortUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]];
//
However the above code throws the following exception:
Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray replaceObjectAtIndex:withObject:]: mutating method sent to immutable object'
Your arrayProduct looks to be NSArray.
Try converting it into NSMutableArray and :
NSMutableArray *mutableProducts = [NSMutableArray arrayWithArray:arrayProduct];
[mutableProducts sortUsingDescriptors:[NSArray arrayWithObject:aSortDescriptor]];
Related
I have a NSMutableArray that has a inner NSMutableArray that I would like to sort (sort the outer items) by a date property within the inner NSMutableArray.
The array looks like this
[
{
messages : [
{
date
},
..... etc
]
},
..... etc
]
The code below is my attempt that throws an exception
NSSortDescriptor *sdSortDate = [NSSortDescriptor sortDescriptorWithKey:#"messages.#lastObject.date" ascending:YES];
events = [NSMutableArray arrayWithArray:[events sortedArrayUsingDescriptors:#[sdSortDate]]];
example
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '[<__NSArrayM 0x604000654670> valueForKeyPath:]: this class does not implement the lastObject operation.'
Any ideas on how I can do this?
You should use messages.date.#lastObject instead of messages.#lastObject.date. Try the code below
NSSortDescriptor *sdSortDate = [NSSortDescriptor sortDescriptorWithKey:#"messages.date.#lastObject" ascending:YES];
events = [NSMutableArray arrayWithArray:[events sortedArrayUsingDescriptors:#[sdSortDate]]];
The following method:
- (NSMutableArray*) timeSortedBegins {
NSMutableArray* begins = [self.spans valueForKey: #"begin"];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey: #"cycleOffsetObject" ascending: YES];
[begins sortUsingDescriptors: #[sort]];
return begins;
}
throws this runtime exception:
2014-03-21 14:41:32.482 myValve[1741:60b] -[__NSArrayI sortUsingDescriptors:]: unrecognized selector sent to instance 0x16d7bc20
2014-03-21 14:41:32.484 myValve[1741:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSArrayI sortUsingDescriptors:]: unrecognized selector sent to instance 0x16d7bc20'
I have used breakpoints to convince myself that the begins array is indeed full of (two in this case) WEAnchor* objects. And that object implements the following two methods:
- (NSTimeInterval) cycleOffset {
return self.offset + (self.datum ? self.datum.cycleOffset : 0.0);
}
- (NSNumber*) cycleOffsetObject {
return [NSNumber numberWithDouble: self.cycleOffset];
}
To be honest, I only added the cycleOffsetObject wrapper method, because I thought maybe it couldn't work with non object values, I was using initWithKey: #"cycleOffset" before that. I have not declared these in the header file as a property, they're just accessor methods, not state. Is that the problem? If it is, how do you sort by the return value of a given selector? Or is it something head smackingly obvious that I'm just missing?
As #dtrotzjr says, it sounds like your array is an immutable, not a mutable array.
You can either use mutableCopy to create a mutable copy and then sort that copy, or use the NSArray method sortedArrayUsingDescriptors: (which operates on an immutable array, and returns a sorted version of the contents as a second immutable array.)
To use mutableCopy, your code might look like this:
- (NSMutableArray*) timeSortedBegins {
NSMutableArray* begins = [[self.spans valueForKey: #"begin"] mutableCopy];
NSSortDescriptor *sort = [[NSSortDescriptor alloc] initWithKey: #"cycleOffsetObject" ascending: YES];
[begins sortUsingDescriptors: #[sort]];
return begins;
}
Check that [self.spans valueForKey: #"begin"] is actually an NSMutableArray before casting it. The error message indicates that the pointer is actually an NSArray
Terminating app due to uncaught exception 'NSUnknownKeyException', reason: '[<__NSCFConstantString 0xa2f4> valueForUndefinedKey:]: this class is not key value coding-compliant for the key name.'
agesArray=[NSMutableArray array];
sortDescriptor *a=[[sortDescriptor alloc]init];
a.name=#"SAS";
a.lastname=#"kumar";
[agesArray addObject:a.name];
sortDescriptor *a1=[[sortDescriptor alloc]init];
a1.name=#"DAMAN";
[agesArray addObject:a1.name];
sortDescriptor *a11=[[sortDescriptor alloc]init];
a11.name=#"AKSHAY";
[agesArray addObject:a11.name];
NSSortDescriptor *sortDesc = [[NSSortDescriptor alloc] initWithKey:#"name" ascending:YES selector:#selector(compare:)];
[agesArray sortUsingDescriptors:[NSArray arrayWithObject:sortDesc]];
Your agesArray contains NSString objects.
[agesArray addObject:a.name]; //see you are adding string here
NSString class does not contain a property called name. So it is crashing.
Probably you may want to do something like
[agesArray addObject:a];
Side note : Give meaningful name to objects/Methods or whatever. Objective C demand it. Don`t use a,a1,a11
I'm getting an exception after attempting to remove an object from a NSMutableDictionary. The relevant code follows. The 'settings' is passed to the method and can be a NSDictionary or a NSMutableDictionary.
NSMutableDictionary *mutableSettings = nil;
if ([settings isKindOfClass:[NSMutableDictionary class]])
mutableSettings = (NSMutableDictionary *)settings;
else
mutableSettings = [[[NSMutableDictionary alloc] initWithDictionary:settings] autorelease];
[mutableSettings removeObjectForKey:#"akey"];
This crashes with
* Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFDictionary removeObjectForKey:]: mutating method sent to immutable object'
Whats wrong with this? Thanks.
The problem here is that both NSDictionary and NSMutableDictionary return __NSCFDictionary as their class, due to the fact that NSDictionary is a class cluster.
I think you will just have to make a mutable copy of the settings dictionary whether it is mutable or not.
NSMutableDictionary *mutableSettings = [settings mutableCopy];
I have an array of NSDictionnary and I would like to sort them by an int value (the key is named "age").
For exemple :
Dic1 : age = 30, sex = male;
Dic2 : age = 24, sex = male;
Array : Dic1, Dic2;
Now with a compare method I would lik to have :
Array : Dic2, Dic1;
I tried lots of things but doesn't work. I as using NSSortDescriptor but it's only available since iOS 4.0 :(
Have you got a solution ?
Thanks !
EDIT :
I wrote a compare method on NSDictionary category :
- (NSComparisonResult)compareGood:(NSDictionary *)otherObject
{
return [[self objectForKey:#"age"] compare:[otherObject objectForKey:#"age"]];
}
But I have this crash error : Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSCFNumber compare:]: nil argument'
The documentation for NSSortDescriptor says:
Available in iOS 2.0 and later.
Likewise for the NSMutableArray method -sortUsingDescriptors:. You should be able to do this:
NSSortDescriptor *descriptor = [[[NSSortDescriptor alloc] initWithKey:#"age"
ascending:YES]
autorelease];
[myArray sortUsingDescriptors:[NSArray arrayWithObject:descriptor];
or, if myArray isn't mutable, do this for the second line:
NSArray *sortedArray = [myArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:descriptor]];