Reputation: 313
In my app, I'm doing audio analysis. Every second, I'm calling some methods, like this one :
- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
int countArray = [array count];
if(!countArray)
return nil;
else if (countArray <= 5 )
return [array valueForKeyPath:@"@avg.doubleValue"];
else
{
// Création et initialisation d'un tableau temporaire
NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:array];
NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
[averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];
for (int j = 0; j < countArray / 3; j++)
{
[averageArray removeLastObject];
[averageArray removeObjectAtIndex:0];
}
NSNumber * average = [averageArray valueForKeyPath:@"@avg.doubleValue"];
return average;
}
}
The problem is that I sometime receive a NSRangeException error (after 1min or a few hours...it depends...) saying that the array index is beyond bounds. The strange thing is that the index is NOT out of bounds... Those methods are only called on the main thread. Thanks in advance for your help !
EDIT 1 : With the help of Anim and Abhinav, I have changed my code as following. It has worked for more than 2hours 45min (which is a record) and then crash with a EXC_BAD_ACCESS code 1 error...
- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
NSArray *arrayCopy = [[NSArray alloc] initWithArray:array]; // CRASH with EXC_BAD_ACCESS error
int countArray = [arrayCopy count];
if(!countArray)
return nil;
else if (countArray <= 5 )
return [arrayCopy valueForKeyPath:@"@avg.doubleValue"];
else
{
// Création et initialisation d'un tableau temporaire
NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:arrayCopy];
NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
[averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];
int startOfRange = countArray / 3;
int rangeLength = countArray - 2 * (countArray / 3);
NSArray* slicedArray = [averageArray subarrayWithRange:NSMakeRange(startOfRange, rangeLength)];
NSNumber * average = [slicedArray valueForKeyPath:@"@avg.doubleValue"];
return average;
}
}
Upvotes: 1
Views: 1275
Reputation: 653
you can do one more thing, just add one condition before the loop: here is the snippet, have added comment:
- (NSNumber *) arrayAverage: (NSMutableArray *)array
{
int countArray = [array count];
if(!countArray)
return nil;
else if (countArray <= 5 )
return [array valueForKeyPath:@"@avg.doubleValue"];
else
{
// Création et initialisation d'un tableau temporaire
NSMutableArray *averageArray = [[NSMutableArray alloc] initWithArray:array];
NSSortDescriptor* desc = [[NSSortDescriptor alloc] initWithKey:@"self" ascending:YES];
[averageArray sortUsingDescriptors:[NSArray arrayWithObject:desc]];
if ([array count] > 0) //Added one condition here---PR Singh
{
for (int j = 0; j < countArray / 3; j++)
{
[averageArray removeLastObject];
[averageArray removeObjectAtIndex:0];
}
}
NSNumber * average = [averageArray valueForKeyPath:@"@avg.doubleValue"];
return average;
}
}
Upvotes: 0
Reputation: 38152
With given piece of code it would more of guessing on whats going on here. Please make sure following:
I would like to induce following statements inside your For loop:
if (averageArray.count > 0) {
[averageArray removeLastObject];
}
if (averageArray.count > 0) {
[averageArray removeObjectAtIndex:0];
}
Upvotes: 2