views:

660

answers:

2

I'm trying to create an array (States) of arrays (Cities). Whenever I try to add an item to my City array I get this error:

'NSInvalidArgumentException', reason: '*** +[NSMutableArray addObject:]: unrecognized selector sent to class 0x303097a0

My code is as follows. The line it errors on is

 [currentCities addObject:city];

I'm sure I've got some Memory Management problem as I still don't understand it all that well. Was hoping someone could explain my mistake to me.

if (sqlite3_prepare_v2(db, sql, -1, &statement, NULL) == SQLITE_OK){
     // We need to keep track of the state we are on
     NSString *state = @"none";
     NSMutableArray *currentCities = [NSMutableArray alloc];

     // We "step" through the results - once for each row
     while (sqlite3_step(statement) == SQLITE_ROW){
      // The second parameter indicates the column index into the result set.
      int primaryKey = sqlite3_column_int(statement, 0);
      City *city = [[City alloc] initWithPrimaryKey:primaryKey database:db];

      if (![state isEqualToString:city.state])
      {
       // We switched states
       state = [[NSString alloc] initWithString:city.state]; 

       // Add the old array to the states array
       [self.states addObject:currentCities];

       // set up a new cities array
       currentCities = [NSMutableArray init];
      }

      [currentCities addObject:city];
      [city release];
     }
    }
+3  A: 

You need to call some sort of initializer on NSMutableArray, don't you? initWithCapacity, or something like that? Not sure what you get if you leave it off.

** Just tested it. Make it [[NSMutableArray alloc] init] and you will be fine.

Amagrammer
+4  A: 

The lines:

// set up a new cities array
currentCities = [NSMutableArray init];

Should read:

// set up a new cities array
[currentCities init];

which should hopefully fix your problem. Instead of initializing your array, you're sending an init message to a class object, which doesn't do anything. Afterwards, you're currentCities pointer is still not initialized.

Even better would be to remove that line and change the 4th line such that you allocate and initialize all in one step:

NSMutableArray *currentCities = [[NSMutableArray alloc] init];
Peter Nix
If you do separate initialization (which you shouldn't, but if you do), it needs to read `currentCities = [currentCities init]`. NSArray initializers never return the receiver, and no class's initializer is guaranteed to do so.
Chuck
The reason I have the [currentCities init]; line is because it will need to initialize a new instance when we switch to the next state.Changing that line did fix this issue but raised another issue, however adding the second step you mentioned ([[NSMutableArray alloc] init]) fixed that issue.Thank you.
Pselus
If you initialize a new instance, you should be allocating a new instance as well.
Wevah