views:

81

answers:

1

I am trying to generate an NSDictonary that can be used to populate a listview with data I retrieved from an SQL statement. when I go to create an array and add them it adds the arrays for ALL my keys and not just for the current key. I've tried a removeAllObjects on the array but for some reason that destroys ALL my data that I already put in the dictionary.

//open the database

 if(sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK)
 {
  const char *sql = "select alphaID, word from words order by word";
  sqlite3_stmt *selectStatement;

  //prepare the select statement
  int returnValue = sqlite3_prepare_v2(database, sql, -1, &selectStatement, NULL);
  if(returnValue == SQLITE_OK)
  {
   NSMutableArray *NameArray = [[NSMutableArray alloc] init];
   NSString *alphaTemp = [[NSString alloc] init];
   //loop all the rows returned by the query.
   while(sqlite3_step(selectStatement) == SQLITE_ROW)
   {
     NSString *currentAlpha = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectStatement, 1)];
     NSString *definitionName = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectStatement, 2)];

   if (alphaTemp == nil){
     alphaTemp = currentAlpha;
    }

    if ([alphaTemp isEqualToString:(NSString *)currentAlpha]) {
    [NameArray addObject:definitionName];

    }
    else if (alphaTemp != (NSString *)currentAlpha) { 
     [self.words setObject:NameArray forKey:currentAlpha];
     [NameArray removeAllObjects];
     [NameArray addObject:definitionName];
    } 
   }
  }

The Statement above adds all the "keys" but then removes all the array elements for all keys. if I take out the removeAllKeys it adds ALL the array elements for ALL keys. I don't want this I want it to add the array elements FOR the specific key then move on to the next key.

in the end I want a NSDictonary with

A (array)
Alpha (string)
Apple (string)
B (array)
Beta (string)
Ball (string)
C (array)
Code (string)
...

+2  A: 

Though I don't think it affects your problem, from the way I read your code, you should change

NSString *alphaTemp = [[NSString alloc] init];

to

NSString *alphaTemp = nil;

since alphaTemp is just used to point to an NSString that is generated initially as currentAlpha. You also should call [NameArray release] at some point below the code you've given, since you alloc'd it.

The real issue is that you are repeatedly adding pointers to the same NSMutableArray to your NSDictionary (self.words). I can see two ways to fix this:

Change

[self.words setObject:NameArray forKey:currentAlpha];

to

[self.words setObject:[NSArray arrayWithArray:NameArray] forKey:currentAlpha];

so that you are adding a newly-created (non-mutable) NSArray to your NSDictionary.

-- or --

Insert

[NameArray release];
NameArray = [[NSMutableArray alloc] init];

after

[self.words setObject:NameArray forKey:currentAlpha];

so that once you've inserted the NSMutableArray into the NSDictionary, you create a new NSMutableArray for the next pass.

Isaac
That makes sense. Thank you. I do find it odd that modifying a mutable array after it gets put in a dictionary affect its results but that's defiantly what is happening.
Ed Wist
The problem is that putting the array in the dictionary is really putting a pointer to that one array (not a copy of the array) into the dictionary, so your original code had the same pointer to that one array for every entry in the dictionary.
Isaac
Yes, and that describes exactly what was happening. Dumping a copy works great. This is actually applicable to many many of my problems. My end application will have the ability to dump data from an SQL DB, XML, and .plists to a "common" Dictionary format that can be utilized with in the app. I'm going to need this method process a few times.
Ed Wist