0

I want to create a NSMutableDictionnary with a NSString.

-(NSMutableDictionary *)getList{
//Declaration d'un objet SQLITE
sqlite3 *database;

//Declaration de notre String qui sera retourne
NSMutableDictionary *aromaArray = [[NSMutableDictionary alloc] init];

// Ouverture de la base de donnees
if(sqlite3_open([databasePath UTF8String], &database) == SQLITE_OK) {

    //Chaine de caracteres de la requete
    const char *sqlStatement = "SELECT name_fr FROM aroma_huiles";

    //Creation de l'objet statement
    sqlite3_stmt *compiledStatement;

    //Compilation de la requete et verification du succes
    if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL) == SQLITE_OK) {

        // Creation d'un dictionnaire des noms de colonnes
        NSDictionary *dictionary = [self indexByColumnName:compiledStatement];
        //char **final = malloc(4096 * sizeof(*final));
        NSMutableArray *array = [[NSMutableArray alloc] init];

        while(sqlite3_step(compiledStatement) == SQLITE_ROW) {

            //Assigne la valeur dans la chaine de caracteres
            char *tab;
            tab = (char*)sqlite3_column_text(compiledStatement, [[dictionary objectForKey:@"name_fr"] intValue]);
            NSString *final = [NSString stringWithUTF8String:tab];
            if (final != nil) {
                NSString *firstLetter = [final substringToIndex:1];
                [aromaArray setObject:final forKey:firstLetter];
            }
        }
    }
    else {
        //Envois une exception en cas de probleme de requete
        NSAssert1(0, @"Erreur :. '%s'", sqlite3_errmsg(database));
    }

    // Finalisation de la requete pour liberer la memoire
    sqlite3_finalize(compiledStatement);

}
else {
    //Envois une exception en cas de probleme d'ouverture
    NSAssert(0, @"Erreur d'ouverture de la base de donnees");
}
//Fermer la base de donnees
sqlite3_close(database);

//Retourne la valeur
return aromaArray;

}

I think this is the easiest method, only 2 lines, but It still reject it :

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString count]: unrecognized selector sent to instance 0x1093180c0'
Nicolas Charvoz
  • 1,509
  • 15
  • 41

5 Answers5

1

What you see is that your array variable is accessed outside of its bounds. There is simply no element after index 66 as it contains only 67 elements.

You are using a hard to read loop constructs when iterating over array. Instead of while in your case you can transform your loops to use the for construct:

for (int j = 0; j < [array count]; j++) {
...
    for (int i = 0; i < [array count]; i++) {
    ...
    }
}

Doing so there's no need anymore for resetting i to 0 and there's no need for increasing i and j outside of the loop header (remove i++ and j++ statements at the bottom of your loops).

Lars Blumberg
  • 19,326
  • 11
  • 90
  • 127
0

Change while (array[j]) to while (j < [array count])

Kumar KL
  • 15,315
  • 9
  • 38
  • 60
user2828120
  • 233
  • 4
  • 13
0

Why don't you directly create dictionary while you fetch data from DB

while(sqlite3_step(compiledStatement) == SQLITE_ROW) {

            //Assigne la valeur dans la chaine de caracteres
            char *tab;
            tab = (char*)sqlite3_column_text(compiledStatement, [[dictionary objectForKey:@"name_fr"] intValue]);
            NSString *final = [NSString stringWithUTF8String:tab];
            if (final != nil && final.length >0) {
//get substring from string here
NSString *firstLetter = [final substringToIndex:1];
//Add objects in dictionary here
                    [aromaArray setObject:final forKey:firstLetter];
            }
        }
Hemant Singh Rathore
  • 2,153
  • 1
  • 24
  • 38
  • I'm Trying to do this : http://pastebin.com/DkVQdrXa But it tells me : [__NSCFString count]: unrecognized selector sent to instance 0x10973e5c0 2014-09-01 10:51:37.711 SQLite-TUO[22126:60b] *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString count]: unrecognized selector sent to instance 0x10973e5c0' – Nicolas Charvoz Sep 01 '14 at 08:50
  • You don't need to use any index you can directly pass string value in dictionary. – Hemant Singh Rathore Sep 01 '14 at 08:56
  • Also put a check for length of string. – Hemant Singh Rathore Sep 01 '14 at 08:57
  • Still the error : *** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[__NSCFString count]: unrecognized selector sent to instance 0x109532470' – Nicolas Charvoz Sep 01 '14 at 09:14
  • ok I think it works , but my dictionnary only contains 1 value per key, it replace the previous value e.g : First time : G = "Great" , Second time : G = "Good",, but I want G = "Great", "Good" (and the error is still there but it comes from the viewcontroller – Nicolas Charvoz Sep 01 '14 at 09:20
0

I think the reason for the crash is these lines

 tab = (char*)sqlite3_column_text(compiledStatement, [[dictionary objectForKey:@"name_fr"] intValue]);
 NSString *final = [NSString stringWithUTF8String:tab];

if the char value is nil and is converted to the string value an exception may come.ie the case appear when basically there is no value in the corresponding row in table.

so try

tab = (char*)sqlite3_column_text(compiledStatement, [[dictionary objectForKey:@"name_fr"] intValue]);
if(tab){
     NSString *final = [NSString stringWithUTF8String:tab];
     //everything else that comes under is to be here
}
Lithu T.V
  • 19,955
  • 12
  • 56
  • 101
0

So I finally manage to fix the problem ! Simple solution, a bit slow but still it works now ! My problem was totally different than what I thought at the begining. I tried to make a Dictionnary with NSString, and the values were replaced at each loop .. So I only got 20 products when I had 84 at the begining, the Dictionnary was built, but It crashed because I nedded a DIctionnary made with NSArray ! I didn't notice that, so I finally find the solution (I will replace the while with for) :

tab = (char*)sqlite3_column_text(compiledStatement, [[dictionary objectForKey:@"name_fr"] intValue]);
            NSString *final = [NSString stringWithUTF8String:tab];
            if (final != nil && final.length >0) {
                [array addObject:final];
            }
        }
        int i = 0;
        int j = 0;
        NSMutableArray *table = [[NSMutableArray alloc] init];
        while (i < [array count])
        {
            NSString *firstLetter = [array[i] substringToIndex:1];
            table = [[NSMutableArray alloc] init];
            while (j < [array count])
            {
                NSString *secondLetter = [array[j] substringToIndex:1];
                if ([secondLetter isEqualToString:firstLetter]) {
                    [table addObject:array[j]];
                }
                j++;
            }
            j = 0;
            [aromaArray setObject:table forKey:firstLetter];
            i++;
        }

Thank you all for your help :)

Nicolas Charvoz
  • 1,509
  • 15
  • 41