Objective-C: copying a returned NSMutableArray - objective-c

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.

Related

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

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.

[__NSCFString count]: Unrecognized selector

I know this has been asked before, but there is no answer that I have found useful.
First off here is my code
// load the .csv file with all information about the track
NSError *error;
NSString *filepath = [[NSBundle mainBundle] pathForResource:#"file" ofType:#"csv" inDirectory:nil];
NSString *datastring1 = [NSString stringWithContentsOfFile:filepath encoding:NSUTF8StringEncoding error:&error];
NSArray *datarow = [datastring1 componentsSeparatedByString:#"\r"];
//fill arrays with the values from .csv file
NSArray *data_seg = [datarow objectAtIndex:0]; //segment number
NSArray *data_slength = [datarow objectAtIndex:1]; //strait length
NSArray *data_slope = [datarow objectAtIndex:2]; //slope
NSArray *data_cradius = [datarow objectAtIndex:3]; //circle radius
NSArray *data_cangle = [datarow objectAtIndex:4]; //circle angle
NSLog(#"%i", [data_seg count]);
Okay, so there is the code, and I read that is has something to do with autorelease, but I was not able to add a retain like NSArray *data_seg = [[datarow objectAtIndex:0] retain]
When I run the code, I get [__NSCFString count]: unrecognized selector sent to instance 0x9d1ad50
Any help is appreciated, I'm not good at programming, and I am very new.
componentsSeparatedByString method returns an NSArray of NSString. Every item that you extract from datarow array is an NSString and an NSString doesn't respond to 'count'. Your code starting at //fill arrays is incorrect. Every objectAtIndex call will return an NSString*.
This is another way of saying that the datatype for data_seg is NSString* (not NSArray*).
With the corrected code snippet, the problem is because data_seg is a string, and -count is not a method of NSString. It seems you think data_seg is an NSArray.
Look at the documentation for -[NSString componentsSeparatedByString:] and see what it returns -- strings! So you get back an array of strings. So what you want is:
NSString *data_seg = [datarow objectAtIndex:0]; //segment number
NSLog(#"my segment number is: %#", data_seg);

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

Getting an NSString out of an NSArray

I am trying to save and read back some application settings stored as NSStrings in an iPhone app and have been having some trouble.
The code to save looks like:
NSMutableArray *array = [[NSMutableArray alloc] init];
[array addObject:accountID];
...
[array writeToFile:[self dataFilePath] atomically:YES];
[array release];
And the code to read looks like (accountID is an NSString*):
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
accountID = [array objectAtIndex:0];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
The read code throws an exception because after the array is released the accountID variable also appears to have been released (moving the NSLog call before releasing the array works fine). So I'm guessing that I'm creating a reference to the array instead of pulling out the actual string contained in the array. I tried several things to create new strings using the array contents but haven't had any luck.
You guess is on the right lines although you have a reference to the 0th element of the array not the array. The array consists of pointers to NSString objects. The Strings will get get released when yhe array is released.
You need to retain the element you are using e/g/
NSArray *array = [[NSArray alloc] initWithContentsOfFile:filePath];
NSString* accountID = [[array objectAtIndex:0]retain];
...
[array release];
NSLog(#"Loading settings for: %#", accountID);
When you release the array the reference to the accountID will also be released. You need to retain it.
accountID = [[array objectAtIndex:0] retain];
Then obviously at some point you need to release it.
try [accountID retain] before you release the array

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