[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]' - objective-c

I want to create an NSArray populating of NSDictionary and print in console the first value of every array's element.
I receive the following error:
Terminating app due to uncaught exception 'NSRangeException',
reason:' -[__NSArrayM objectAtIndex:]: index 2 beyond bounds [0 .. 1]'
* First throw call stack: (0x30d77e83 0x3b0d46c7 0x30cadd95 0xb93b3 0xb8e03 0x3175ccdd 0x30d42e7f 0x30d42a9b 0x30d40e23 0x30cab471
0x30cab253 0x359e52eb 0x33560845 0xb8abd 0x3b5cdab7)
libc++abi.dylib: terminating with uncaught exception of type
NSException
-(void) listOp {
NSDictionary *dictionary;
NSMutableArray *array;
NSNumber *refNum;
int numOp = [_refNum intValue];
self.array = [NSMutableArray arrayWithObjects: self.dictionary, nil];
for ( int i = 0; i < numOp; i++){
[self.array insertObject:self.dictionary atIndex:i];
NSDictionary* vardebug = nil;
vardebug = [self.array objectAtIndex:numOp];
NSString *valuekey = [self.dictionary valueForKey: #"key"];
NSLog(#"Valuekey is: %#", valuekey);
}
}
Don't understand what is going wrong.

Your code is a little bit messy. You declare:
NSDictionary *dictionary;
NSMutableArray *array;
And after that you call
self.dictionary...
self.array...
You use self if you have property, for example;
#property(nonatomic, strong) NSDictionary *dictionary;
so basically if you want to access your:
NSDictionary *dictionary;
NSMutableArray *array;
you should call, for example:
array = [NSMutableArray arrayWithObjects: dictionary, nil];
Without self. But maybe you have both ivar shown in this example and property and you do it by purpose. I just want to say that if you do it by purpose you should use different names just to make your code more clear.
The error you have happened in line:
vardebug = [self.array objectAtIndex:numOp];
In your first loop iteration you have already one item in the array (added during allocation) and you insert another one so you array contains 2 object but you numOp is equal 2 which refer to 3rd object in the array (array are zero base) so the call is beyond bounds. I guess you want to change it to:
vardebug = [self.array objectAtIndex:i];
Hope this help

Replace vardebug = [self.array objectAtIndex:numOp]; by vardebug = [self.array objectAtIndex:i]; should avoid the crash.

Related

why does __block not adding values to array

I am enumerating ranges inside a block and storing the values inside an array. I expected using __block should store the values inside block into array?
__block NSMutableArray *array;
[indexSet enumerateRangesUsingBlock:^(NSRange range,BOOL * stop ) {
[array addObject:#(range.location)];
[array addObject:#(range.length)];
NSLog(#"location is %d, %ld", range.location, range.length);
}];
NSLog(#"%#",array );
But this result in
location is 4, 2 location is 8, 2 location is 14, 2
and for array
(null)
I expected array to be filled with values.
You have to initialize it, a just declared array is nil:
__block NSMutableArray *array = [NSMutableArray array];
(The Swift compiler would throw an error ... 😉 )
__block NSMutableArray *array = [NSMutableArray array];
It does work fine.
However when I declared array as property then block became redundant.

NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array when checking NSPasteboard

When I do a check to validate to make sure copiedItems array has something it in, I am receiving the error: NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array
NSArray *classes = [[NSArray alloc] initWithObjects:[NSString class], nil]; NSDictionary *options = [NSDictionary dictionary];
NSArray *copiedItems = [pasteboard readObjectsForClasses:classes options:options];
if ([copiedItems objectAtIndex:0]!= nil){
NSString *copiedString = [copiedItems objectAtIndex:0];
Turns out I was causing the error with my check. By calling [copiedItems objectAtIndex:0], I was accessing the array right then, instead of seeing if it was valid first (my original intention). By changing [copiedItems objectAtIndex:0] to if ([copiedItems count]> 0)
I was able to not access copiedItems until I could validate.
A good expansion from #H2CO3: [array objectAtIndex:index] != nil doesn't make sense - NSArrays cannot contain nil

Objective-C: copying a returned NSMutableArray

I am calling a method getHoleScore that populates a NSMutableArray and returns it. I'm trying to copy the array so that the calling method can access the items but I get this exception every time:
exception 'NSRangeException', reason: '* -[__NSArrayM objectAtIndex:]: index 0 beyond bounds for empty array'
I've tried multiple different ways of copying an array that I've found on this site but nothing seems to work. Here's the code:
Score *theScore = self.roundScore;
NSMutableArray *scores = [[[self delegate]getHoleScore:self score:theScore] mutableCopy];
NSInteger total = 0;
if (theScore) {
self.playerName.text = theScore.name;
self.courseName.text = theScore.course;
self.hole1Field.text = [NSString stringWithFormat:#"%d", [[scores objectAtIndex:0] integerValue]];
self.hole2Field.text = [NSString stringWithFormat:#"%d", [[scores objectAtIndex:1] integerValue]];
self.hole3Field.text = [NSString stringWithFormat:#"%d", [[scores objectAtIndex:2] integerValue]];
self.hole4Field.text = [NSString stringWithFormat:#"%d", [[scores objectAtIndex:3] integerValue]];
self.hole5Field.text = [NSString stringWithFormat:#"%d", [[scores objectAtIndex:4] integerValue]];
etc.
Any idea on how to populate the scores array?
You are reaching 0 for your mutable array because it hasn't been alloc/init yet. you either have to place this NSMutableArray *myscores = [NSMutableArray array]; above you [[self delegate] ] call.
Or a better way to do this would be creating your myscores and pass the method in with a this built in nsarray super class method, which takes care of alloc/init your array.
NSMutableArray *myscores =
[NSMutableArray arrayWithArray:[[self delegate] getHoleScore:self
score:theScore];
also make sure that
[[self delegate]getHoleScore:self score:theScore]is not sending you a empty array, calling a -objectAtIndex:a on a empty array will crash your code. A good way to check if your array is empty or not is calling the method -count method on your array, calling count on a array won't crash your code, even if it's zero.
Hey thanks for the help everyone. You were right that getHoleScore returned something nil. It was working off an sqlite database but once I cleared it and then re-added the data, everything worked fine.

NSArray elements from parsed .xml file not accessible on iPhone, using TouchXML

I have an NSMutableArray *myArray, wich is the result of a properly .xml parsed file, using TouchXML.
I just want to extract all elements with key name and store then in a separate NSMutableArray, but my final NSMutableArray *namesList is not accessible, crashing my iPhone app right away, because it only contains the last enumerated string and not the whole array.
Here is the code:
NSMutableArray *namesList = [[NSMutableArray alloc] initWithArray:myArray copyItems:YES];
int i;
for (i = 0; i < [myArray count]; i++)
{
namesList = [[myArray objectAtIndex:i] objectForKey:#"name"];
NSLog(#"All Names: %#", namesList);
}
NSLog(#"First Name: %#", [namesList objectAtIndex:0]); <-- crashing line
And here is the NSLog:
-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x6a42540
2012-04-04 10:34:07.882 Sections[3610:f803] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString objectAtIndex:]: unrecognized selector sent to instance 0x6a42540'
You should be able to do this:
NSMutableArray * namesList = [NSMutableArray alloc] init];
for(i = 0; i < [myArray count]; i++)
{
NSString * tempString = [NSString stringWithString:[[myArray objectAtIndex:i] objectForKey:#"name"]];
[namesList addobject:tempString];
}
NSLog(#"First Name: %#", [namesList objectAtIndex:0]);
[[myArray objectAtIndex:i] objectForKey:#"name"]; returns an NSString object and not another array therefore you can't send an objectAtIndex to it. Check the structure of your arrays.

Several Objective-C objects become Invalid for no reason, sometimes

- (void)loadLocations {
NSString *url = #"<URL to a text file>";
NSStringEncoding enc = NSUTF8StringEncoding;
NSString *locationString = [[NSString alloc] initWithContentsOfURL:[NSURL URLWithString:url] usedEncoding:&enc error:nil];
NSArray *lines = [locationString componentsSeparatedByString:#"\n"];
for (int i=0; i<[lines count]; i++) {
NSString *line = [lines objectAtIndex:i];
NSArray *components = [line componentsSeparatedByString:#", "];
Restaurant *res = [byID objectForKey:[components objectAtIndex:0]];
if (res) {
NSString *resAddress = [components objectAtIndex:3];
NSArray *loc = [NSArray arrayWithObjects:[components objectAtIndex:1], [components objectAtIndex:2]];
[res.locationCoords setObject:loc forKey:resAddress];
}
else {
NSLog([[components objectAtIndex:0] stringByAppendingString:#" res id not found."]);
}
}
}
There are a few weird things happening here. First, at the two lines where the NSArray lines is used, this message is printed to the console-
*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSCFDictionary count]: method sent to an uninitialized mutable dictionary object'
which is strange since lines is definitely not an NSMutableDictionary, definitely is initialized, and because the app doesn't crash.
Also, at random points in the loop, all of the variables that the debugger can see will become Invalid. Local variables, property variables, everything. Then after a couple lines they will go back to their original values. setObject:forKey never has an effect on res.locationCoords, which is an NSMutableDictionary. I'm sure that res, res.locationCoords, and byId are initialized.
I also tried adding a retain or copy to lines, same thing. I'm sure there's a basic memory management principle I'm missing here but I'm at a loss.
Your -[NSArray arrayWithObjects:] call must end with a nil (because a C function needs it to determine how many arguments you gave it).
I don't see anything obviously wrong with memory management here. Maybe add some error checking:
check the error: parameter of initWithContentsOfURL:
check locationString != nil
check lines != nil