Working with ObjectAtIndex gives beyond bounds error - iphone

I want to do something really simple but I get an error, what I'm missing?
int i;
int count;
TutorialAppDelegate *appDelegate = (TutorialAppDelegate *)[[UIApplication sharedApplication] delegate];
Animals *aAnimal = (Animals *)[appDelegate.animals objectAtIndex:i];
count = [animals count];
if (i < count)
{
NSLog(#"%#",aAnimal.animalName);
}
ERROR:
'*** -[NSMutableArray objectAtIndex:]: index 22510243 beyond bounds [0 .. 5]'
The 0...5 is correct! There are only 6 values in the array.
And use
NSLog(#"%#",aAnimal.animalName);
out of the if function returns the right value, when I also change the i to 0 ofcourse.

You need to initialise i.
int i = 0;
By default ints are not set to zero or anything sensible. You can check this by adding a line such as:
NSLog(#"Value of i without initialising is: %d", i);

please intialise your mutable array-
appDelegate.animals=[[NSMutableArray alloc] initWithArray:(NSArray *)array];
and check out your array, have you mention nil object at the end of your array elements-
NSMutableArray* animals=[[NSMutableArray alloc]
initWithObjects:#"one 1",#"two 2",nil];

Related

NSMutable Array beyond bounds

I have a block of code which when executed gives me this error. And I am relatively new, I can't seem to fix the problem.
Error:
2011-09-06 12:31:06.094 ForceGauge[266:707] CoreAnimation: ignoring exception: * -[NSMutableArray objectAtIndex:]: index 1 beyond bounds [0 .. 0]
-(void)peakCollector:(NSMutableArray *)testarray {
NSUInteger totalRows = [testarray count];
NSMutableArray *percentArray = [[NSMutableArray alloc]initWithObjects:0, nil];
if(forcecontroller.selectedSegmentIndex==0)
testarray = lbData;
else if(forcecontroller.selectedSegmentIndex==1)
testarray = kgData;
else if(forcecontroller.selectedSegmentIndex ==2)
testarray = ozData;
else if(forcecontroller.selectedSegmentIndex ==3)
testarray = newtonData;
for(int i = 0; i< totalRows-1; i++) {
if ([[testarray objectAtIndex:i+1] doubleValue] >= 1.2 * [[testarray objectAtIndex:i] doubleValue]) {
percentArray = [testarray objectAtIndex:i];
DatabaseTable *tableVC = [[DatabaseTable alloc] initWithStyle:UITableViewStylePlain];
[self.navigationController pushViewController:tableVC animated:YES];
if(forcecontroller.selectedSegmentIndex==0)
[tableVC copydatabase:percentArray];
else if(forcecontroller.selectedSegmentIndex==1)
[tableVC copydatabase:kgData];
else if(forcecontroller.selectedSegmentIndex==2)
[tableVC copydatabase:ozData];
else if(forcecontroller.selectedSegmentIndex==3)
[tableVC copydatabase:newtonData];
[tableVC release];
} else {
[analogData removeAllObjects];
}
}
}
There are multiple issues here:
1) NSArrays can only contains NSObjects.
In your code, you are initializing your NSArray using [[NSMutableArray alloc]initWithObjects:0, nil];, but 0 is an atomic type, not an NSObject
(and basically 0 is the same value as nil (nil and NULL are typically equal to 0, interpreted as the id and void* types, respectively)
You have to encapsulate your 0 value in an NSNumber instead :
[[NSMutableArray alloc]initWithObjects:[NSNumber numberWithInt:0], nil];
Then retrieve the NSNumber using [percentArray objectAtIndex:0] and finally convert back the retrieve NSNumber to int using NSNumber's intValue method:
NSNumber* number = [percentArray objectAtIndex:0]; // returns an NSNumber which is an NSObject encapsulating numbers, see Apple's documentation
int val = [number intValue]; // retrieve the integer value encapsulated in the NSNumber
// or directly:
// int val = [[percentArray objectAtIndex:0] intValue];
2) The exception you got is in fact elsewhere and is much more subtle: you are retrieving the [testarray count] value in an NSUInteger variable, which is an unsigned type. Then totalRows-1 will do some tricky things if totalRows is equal to 0 (which is obviously the case considering the exception you have).
As totalRows is an NSUInteger, when it is equal to 0, totalRows-1 will not be equal to -1, but to... (NSUInteger)-1 (-1 interpreted as an unsigned integer), which is 0xFFFFFFFF, or namely the maximum value of the NSUInteger type!
This is why i is always less than this totalRows-1 value (as this value is not -1 but 0xFFFFFFFF = NSUInteger_MAX).
To solve this issue, cast your totalRows variable to an NSInteger value, or add a condition in your code to treat this special case separately.
Please check the how many objects test array contains at beginning of for loop.
Other thing that can help is that avoid NSUInteger and use simple int for storing array count.
Please post if this don't work.
The error simply means that you're trying to retrieve an object at an index that does not exist. In your specific case, the array you're trying to get the object from does not have an object at index 1
An easy example
[0] => MyCoolObject
[1] => MySecondObject
[2] => ObjectTheThird
You can access indexes 0,1,2 of your array as they contain objects. If you now would try to access index 3 it would throw the Out of bounds exception as index 3 does not exist.

Memory Leak Field Variable

I do not undserstand why I cannot simply add [sortedArray release]; at the end of this method. Everytime I do, it crashes.
- (void)viewWillAppear:(BOOL)animated {
[super viewWillAppear:animated];
NSString *workoutName = [event.assignedWorkout valueForKey:#"name"];
self.title = workoutName ;
NSMutableArray *sortedArray = [[NSMutableArray alloc]init];
// Sort ExerciseArray
int y = 0;
int x= 0;
do{
if ([[[exerciseArray objectAtIndex:y] index]intValue] == x){
[sortedArray addObject:[exerciseArray objectAtIndex:y] ];
x++;
}
if (y<[exerciseArray count]-1){
y++;
}else {
y=0;
}
}
while(x <= [exerciseArray count]-1);
exerciseArray = sortedArray;
[self.tableView reloadData];
}
If anyone can point me in the right direction or refer me to some documentation, it would be very much appreciated.
You are assigning the array to the exerciseArray variable and then you are releasing the array. The next time you try to access the exerciseArray variable, the array will be gone, because assigning it to the exerciseArray variable doesn't increase its retain count.
The array object's retain count is 1 when you first call alloc. When you assign it to exerciseArray, its retain value is still 1. Then, when you release it, its retain count drops to 0 and you can't expect to access the array again.
You should either not release it (my preference), or else explicitly retain it by calling:
[exerciseArray release];
exerciseArray = [sortedArray retain];
[sortedArray release];
Note the order of those two messages. The first line releases any existing object pointed to by the exerciseArray variable. The second line raises the new array's retain count to 2, and the second then drops it to 1, so the array is still retained. If you release sortedArray before assigning the new array to the exerciseArray variable, the retain count becomes 0 and you will lose it before you can assign it to the new variable.
You probably wanted to do:
[exerciseArray release];
exerciseArray = sortedArray;
[self.tableView reloadData];
BTW, you can sort an Array using a block with sortedArrayUsingComparator.

How to determine the index number of the last object in a NSMutable Array

I have a NSMutable Array and was trying to find the index number of the last object in this array. I tried this, but it feels cumbersome:
int currentCount = [[[self.myLibrary objectAtIndex:currentNoteBookNumber] tabColours] count];
NSLog(#"Number of tab colours total: %i", currentCount);
NSLog(#"Index number of last object: %i", currentCount-1);
Is there another way of doing this? The context of my problem is that I need to determine the last object in order to change it:
replaceObjectAtIndex:[last object] withObject: ...
Thanks!
If you need the index, then that is the way to do it (int lastIndex = [array count] - 1;). If you just want to replace the last object with a different object however, you can do:
[array removeLastObject];
[array addObject: newLastObject];
Try this:
[myArray replaceObjectAtIndex:[myArray count]-1 withObject:someNewObject];
If you add objects to your NSMutableArray with addObjects: method it always put elements at the end. When you removeObjectAtIndex:index it automatically shift down on 1 position all elements with indexes > index. That is why the last object in array is always have index [array count] - 1. I do not tell you about replacing objects, I just tell about adding objects.
int index=[*yourarrayname* indexOfObject:[*yourarrayname* lastObject]];
NSLog(#"index=%d",index);
Use this snippet:
int lastIndex = [YOUR_ARRAY count] - 1;
this will gives you last index of your array.

iPhone Application crashes

When I do the following my application crashes and I get an error (terminate called after throwing an instance of 'NSException') whenever i run the simulation:
for (...)
[Array1 replaceObjectAtIndex:i withObject: [NSString stringWithFormat:#" Trip %i",i+1]]
OK after writing the problem I have found that the error is "0 is beyond bounds for empty array".
You really really really need to post the type of exception and your code to give us a reasonable chance of solving your problem. However, I'm going to taker a shot at it anyway.
My guess is your code looks something like this:
Array1 = [[NSMutableArray alloc] initWithCapacity: someNumber];
for (i = 0 ; i < someNumber ; ++i)
{
[Array1 replaceObjectAtIndex:i withObject: [NSString stringWithFormat:#" Trip %i",i+1]];
}
All arrays start out with 0 objects in them even if you use -initWithCapacity:. That method only provides a hint to the runtime that the array will grow to the specified size at some point. You need to use -addObject:.
Edit
Yep, from your edit, I'm sure I am right. The array has started out empty and you are trying to replace the object at index 0 which isn't there yet.
The code above should be changed as follows:
array1 = [[NSMutableArray alloc] initWithCapacity: someNumber]; // fixed naming convention too :-)
for (i = 0 ; i < someNumber ; ++i)
{
[array1 addObject: [NSString stringWithFormat:#" Trip %i",i+1]];
}
-addObject: adds the new objects to the end of the array.
If you want something that looks more like a C or Java array, you can prefill the array with NSNull objects
array1 = [[NSMutableArray alloc] initWithCapacity: 6]; // fixed naming convention too :-)
for (i = 0 ; i < 6 ; ++i)
{
[array1 addObject: [NSNull null]];
}
// Now the following will work
[array1 replaceObjectAtIndex: 4 withObject: #"foo"];
if you are using replaceObjectAtIndex method with NSArray array type object, there is possibility of getting exception (crashed).
Use NSMutableArray for managing a modifiable array of objects.
Although replaceObjectAtIndex can also be raised the following Exception for Object and Index
Index: Raises an NSRangeException if index is beyond the end of the array.
Object: Raises an NSInvalidArgumentException if Object you are passing is nil.
Ok, here is a guess (I can't do better without more information):
You cannot change an object you are iterating over.
(Bad) Example:
for (NSObject *obj in Array1){
[Array1 replaceObjectAtIndex:i withObject: [NSString stringWithFormat:#" Trip %i",i+1]]
}

NSMutable Array

I have a NSMutableArray:
NSMutableArray *temp = //get list from somewhere.
Now there is one method objectAtIndex which returns the object at specified index.
What I want to do is that, I want to first check whether an object at specified index exists or not. If it exists than I want to fetch that object. Something like:
if ([temp objectAtIndex:2] != nil)
{
//fetch the object
}
But I get exception at the if statement saying that index beyond bound.
Please anyone tell me how to achieve this.
you cannot have 'empty' slots in an NSArray. If [myArray count]==2 ie array has two elements then you know for sure that there is an object at index 0 and an object at index 1. This is always the case.
Check the length first using the count method.
if ([temp count] > indexIWantToFetch)
id object = [temp objectAtIndex:indexIWantToFetch];
you could do this way:
When you initialize, do something like:
NSMutableArray *YourObjectArray = [[NSMutableArray alloc] init];
for(int index = 0; index < desiredLength; index++)
{
[YourObjectArray addObject:[NSNull null]];
}
Then when you want to add but check if it already exists, do something like this:
YourObject *object = [YourObjectArray objectAtIndex:index];
if ((NSNull *) object == [NSNull null])
{
/// TODO get your object here..
[YourObjectArray replaceObjectAtIndex:index withObject:object];
}
Just check that the index is >= 0 and < count
Returns the number of objects currently in the receiver.
- (NSUInteger)count
int arrayEntryCount = [temp count];
First of all you check the length of array-
NSMutableArray *temp = //get list from somewhere.
now check-
if(temp length)
{
Your objectclass *obj = [temp objectAtIndex:indexnumber];
// indexnumber is 0,1,2 ,3 or anyone...
}