views:

482

answers:

2

I wrote this function in a Helper class for reading a table from my database, and returning it to my controller.

On my viewdidload, i cache this result into a class variable (retain property set) and trying to use that inside a picker view control's delegate method. (titleForRow)

Somehow, I get a EXC_BAD_ACCESS when I try to access the values I boxed into the NSMutableDictionary, in the delegate methods.

 + (NSMutableDictionary*) getAllInterchanges {

NSMutableDictionary *interchanges = NSMutableDictionary alloc init;
NSString *sqlString = NSString stringWithFormat:@"SELECT * FROM Interchanges";
const char *sql = sqlString UTF8String;
sqlite3_stmt *statement;
// Preparing a statement compiles the SQL query into a byte-code program in the SQLite library.
// The third parameter is either the length of the SQL string or -1 to read up to the first null terminator.
if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
// We "step" through the results - once for each row.
while (sqlite3_step(statement) == SQLITE_ROW) {

Interchanges ic;
ic.name = NSString stringWithUTF8String:(char *)sqlite3_column_text(statement, 0);
ic.id = sqlite3_column_int(statement, 1);

NSValue *boxedInterchange = NSValue valueWithBytes:&ic objCType:@encode(Interchanges);

interchanges setObject:boxedInterchange forKey:ic.id;
}
}
// "Finalize" the statement - releases the resources associated with the statement.
sqlite3_finalize(statement);

interchanges autorelease;
return interchanges;

}

I even tried commenting out the last autorelease statement. Still it's giving me the same exception...

Please help...

A: 

You code formatting is messed up which is not really helping... but one problem I see is:

[interchanges setObject:boxedInterchange forKey:ic.id];

ic.id is, I assume, an integer but the key field needs to be an object. Not sure if this would cause the crash but it is wrong. Try something like:

[interchanges setObject:boxedInterchange forKey:[NSNumber numberWithInt:ic.id]];

Your autorelease at the end is okay (as long as you retain in the method that calls it). You use of autorelease NSString and NSValue is also okay as the array retains its values (and copies its key).

Stephen Darlington
+1  A: 

I'm assuming that Interchanges is a struct, since you are boxing it with an NSValue? If so, you have an ownership problem with your 'name' field. A struct won't retain the string you are giving it, so it won't last beyond the current autorelease pool; what you are boxing is a struct containing an int and a pointer to memory that is about to become invalid. You could manually retain the NSStrings before assigning them to 'name', but then you'd have to be very careful to release them manually later or you would leak.

Is there some reason you can't just make Interchanges an NSObject subclass that can manage the NSString member itself, and store that directly in the dictionary rather than boxing a struct?

smorgan
Yes, Interchanges is a struct... I'll try changing it to a NSObject class. I think that wud work as my "content" was getting corrupted rather than the pointer itself...Thanks
Mugunth Kumar
I thought it would be an overkill...to use NSObject instead of a struct... Anyways... din't strike me... :D thanks a ton smorgan...It worked... :D
Mugunth Kumar