Array index beyond bounds - objective-c

When I run the code below I get
Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[NSCFArray objectAtIndex:]
I understand that at some point in the loop not existed index of the array is reached.
How to deal with that ?
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSArray *t = [NSTimeZone knownTimeZoneNames];
for(id x in t)
{
NSArray *tmpArray = [x componentsSeparatedByString:#"/"];
NSLog(#"%#", [tmpArray objectAtIndex:1]);
}
[pool drain];
return 0;
}

Not all time zones names contain a slash. For example, the UTC time zone name does not contain a slash. So tmpArray might only contain one string, at index 0.
Perhaps this will do what you want:
NSLog(#"%#", [tmpArray lastObject]);

You should check the size of tmpArray first:
NSArray *tmpArray = [x componentsSeparatedByString:#"/"];
if ([tmpArray count] > 1)
NSLog(#"%#", [tmpArray objectAtIndex:1]);

You may want to check the size of tmpArray before accessing index 1

Related

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.

How to copy from NSMutableArray to NSMutableString?

Im trying to add some strings into NSMutableArray,than want to copy element 0(zero)
from NSMutableArray to NSMutableString
[MS appendString:str]
this line raises error.
what is the problem ?
a MutableArray element cannot be assigned to NSString ?
(thanks for any responses)
error output is :
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFNumber length]: unrecognized selector sent to instance 0x6c82440'
here is my code :
NSMutableArray *A=[[NSMutableArray alloc]init];
NSMutableString *MS=[NSMutableString stringWithString:#"first"];
for (int i=0; i<=15;i+=2) {
[A addObject:[NSNumber numberWithInteger:i]];
}
NSString *str;
for (int x=0; x<[A count]; x++) {
str=[A objectAtIndex:0];
[MS appendString:str];//ERROR HERE
}
[A release];
You are adding NSNumbers to the array and not strings n the folioing line:
[A addObject:[NSNumber numberWithInteger:i]]; // here you are adding numbers
So when you read them from the array later, they are still numbers and you have to create strings from them:
NSString *str;
NSNumber *number;
for (int x=0; x<[A count]; x++) {
number = [A objectAtIndex:0]; // You should probably replace 0 by x here.
str = [number stringValue]; // transform number into a string
[MS appendString:str];
}
[A release];
But if you want the array to store strings and not numbers, then replace the first loop instead with the following:
for (int i=0; i<=15;i+=2) {
[A addObject:[[NSNumber numberWithInteger:i] stringValue]];
}
Or
for (int i=0; i<=15;i+=2) {
[A addObject:[NSString stringWithFormat:#"%d", i]];
}

Method Creates an Array with 11 objects, All Out of Scope, Unrecognized Selector Results

Okay, so, I'm doing a simple lookup. I have an array of NSString objects and a string to search for in the array's elements.
It all seems to work up until I try to add a match to a new mutable array made to hold the search results. The stringHolder variable gets the string, and resultsCollectorArray even get the right number of new elements, but each element is empty and "out of range". Here's the method:
#implementation NSArray (checkForString)
-(NSMutableArray *) checkForString: (NSString *) matchSought
{
long unsigned numberofArrayElements;
long unsigned loop = 0;
NSRange searchResults;
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init];
id stringHolder;
numberofArrayElements = [self count];
while (loop < numberofArrayElements) {
searchResults.length = 0;
searchResults = [[self objectAtIndex: loop] rangeOfString: matchSought options:NSCaseInsensitiveSearch];
if (searchResults.length > 0) {
stringHolder = [self objectAtIndex: loop];
[resultCollectorArray addObject: stringHolder];
}
loop++;
}
return [resultCollectorArray autorelease];
}
Once we get back to the main portion of the program, I get an unrecognized selector sent to the mutable array that was supposed to receive the result of the method. Here's the main section:
#import <Foundation/Foundation.h>
#import "LookupInArray.h"
int main (int argc, const char * argv[])
{
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
NSString *testString = [[NSString alloc] initWithString: #"ab"];
NSMutableString * resultString = [[NSString alloc] init];
NSArray * theArray = [[NSArray alloc] initWithObjects: ..., nil]; // Actual code has the objects
NSMutableArray *resultArray = [[NSMutableArray alloc] init];
NSUInteger arrayCount = 0;
unsigned long loops = 0;
resultArray = [theArray checkForString: testString];
arrayCount = [resultArray count];
while (loops < arrayCount){
resultString = [resultArray objectAtIndex: loops]; // Here's where we get the unrecognized selector.
NSLog(#"%#", resultString);
loops++;
}
[pool drain]; // Also, I'll release the objects later. I just want to get what's above working first.
return 0;
}
I've searched the other answers (for hours now), but didn't seen anything that solved the issue.
Any and all help would be really appreciated.
And thanks beforehand.
NSMutableArray * resultCollectorArray = [[NSMutableSet alloc] init]; is so incorrect. You are creating a mutable set and assigning it to a mutable array.
You are getting unrecognized selector because objectAtIndex: is not a valid selector for NSMutableSet. Make that statement,
NSMutableArray * resultCollectorArray = [[NSMutableArray alloc] init];
A Better way
NSArray * filteredArray = [array filteredArrayUsingPredicate:[NSPredicate predicateWithFormat:#"SELF contains[cd] %#", searchString]];
You can directly filter the array using predicates. This way you do this in a single step. :)

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

Concatenating NSArray contents with NSMutableString AppendString

I'm trying to iterate through an NSArray and keep getting a compiler error right when i try concatenating the contents of my array at position i to my NSMutableString instance..
It just tells me that there's a "syntax error before ;" which doesn't tell me a whole lot.
at this line:
[output appendString:[widget.children objectAtIndex:i];
i know there must be something up with my syntax..
my function is as follows
- (NSString *)readArray
{
NSMutableString *output = [[NSMutableString alloc] init];
int i;
int arraySize = widget.children.count;
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
for (i = 0; i < arraySize; i++)
{
[output appendString:[widget.children objectAtIndex:i]; (throws error here)
}
[pool release];
return output;
}
thanks in advance
NSArray has a method that does exactly what you're doing as well:
- (NSString *)readArray {
return [widget.children componentsJoinedByString:#""];
}
Also, unless you're calling that function fairly frequently in a tight loop there's not much advantage to having it create its' own autorelease pool.
you have an unclosed bracket
you need ]] at the end instead of ]