Memory Leak 'Select Statement' iPhone - iphone

Hi after several hours searching i have found the function which gives me memory leaks. The leaks i get are:
Leaked Object#AddressSize Responsible Library Responsible Frame
NSCFString 2 < multiple > 32 Foundation
-[NSPlaceholderString initWithBytes:length:encoding:]
i cant see anything wrong with this code. any help would be gratefully received Dan
-(void)readItems {
if (!database) return; // earlier problems
// build select statement
if (!selStmt)
{
const char *sql = "SELECT * FROM Demotivate order by name asc;";
if (sqlite3_prepare_v2(database, sql, -1, &selStmt, NULL) != SQLITE_OK)
{
selStmt = nil;
}
}
if (!selStmt)
{
NSAssert1(0, #"Can't build SQL to read items [%s]", sqlite3_errmsg(database));
}
// loop reading items from list
[items removeAllObjects]; // clear list for rebuild
int ret;
while ((ret=sqlite3_step(selStmt))==SQLITE_ROW)
{ // get the fields from the record set and assign to item
// primary key
NSInteger n = sqlite3_column_int(selStmt, 0);
Item *item = [[Item alloc] initWithPrimaryKey:n]; // create item
// item name
char *s = (char *)sqlite3_column_text(selStmt, 1);
if (s==NULL) s = "";
item.name = [NSString stringWithUTF8String:(char *)s];
// quantity needed
item.howOften = sqlite3_column_int(selStmt, 3);
// noted
s = (char *)sqlite3_column_text(selStmt, 2);
if (s==NULL) s = "";
item.Cost = [NSString stringWithUTF8String:(char *)s];
s = (char *)sqlite3_column_text(selStmt, 4);
if (s==NULL) s = "";
item.income = [NSString stringWithUTF8String:(char *)s];
s = (char *)sqlite3_column_text(selStmt, 5);
if (s==NULL) s = "";
item.wage = [NSString stringWithUTF8String:(char *)s];
[items addObject:item]; // add to list
[item release];
// free item
}
sqlite3_reset(selStmt); // reset (unbind) statement
}

Probably you forgot to release item.name in Item's dealloc.

Related

Save UISwitch state in to sqlite database and access the same for display

I have a form contains text fields,a textView and 2 switches.Now I am using sqlite database for saving data in to database.Every thing is fine with text fields,text view saving,retrieving and even displaying the saved.As we know we don't have any feature called check box,we need to make use of switch which behaves/acts as that of check box functionality.Now while saving the switch state in to the database.I am saving it as a string/text format only,i.e. check the state of switch,assign value as '1' for ON and '0' for OFF to an integer.Now you might get a bit confused how can I save the integer to string format,yes you are right!I am converting the int value in to number and finally number to string.Then I have formed the query and have inserted the values in to sqlite database table.
Here is the code snippet of it for clear understanding:
int smsValue = 0;
if ([smsSwitch isOn])
{
smsValue = 1;
}
else
{
smsValue = 0;
}
NSNumber *smsNum = [NSNumber numberWithInt:smsValue];
NSString *selectedVal = [smsNum stringValue];
The selectedVal is what we are going to pass as string while forming the query,I also have found out that the state is getting saved properly,i.e. the value is correct.
Now I have a requirement,in my form I have switch for sms,Initially the state of that switch is Off,during off state,the last 2 fields i.e. textField and textView are hidden.If the user selects it (i.e. state is ON),then both the fields are said to be open to enter the values.
Totally I have saved 3 reminders,out of which I have saved 2 with out sms and 1 with sms and both the fields(last) filled.Now to pass the data,or to keep track of record saved after filling the form I have used a model class,please see the following snippet for clear understanding...how I have passed values for other fields(textFields):
-(void)viewDidLoad
{
textField.text = reminderInstance.Name;
textField1.text = reminderInstance.Event;
textField2.text = reminderInstance.Date;
textField3.text = reminderInstance.numDays;
textField4.text = reminderInstance.remGroup;
[super viewDidLoad];
}
Here the reminderInstance is object of the model class holding values like name,event,date etc...Now last 2 fields i.e. textField5 and textView are tied or linked to state of sms switch.If it is selected we need to consider both the fields values and pass them for user to edit/make changes.If not we need not bother about the last 2 fields.
Here is the action for the switch:
-(IBAction)toggleEnabledForswitch:(id)sender
{
if(smsSwitch.on)
{
textField5.hidden = NO;
textView.hidden = NO;
}
else
{
textField5.hidden = YES;
textView.hidden = YES;
}
}
Now in save action,I am checking the state of the switch and saving the values accordingly,the following code snippet will show a clear picture:
-(IBAction)save:(id)sender
{
int smsValue = 0;
if ([smsSwitch isOn])
{
smsValue = 1;
}
else
{
smsValue = 0;
}
NSNumber *smsNum = [NSNumber numberWithInt:smsValue];
NSString *selectedVal = [smsNum stringValue];
reminderInstance.smsString = selectedVal;
sqlite3_stmt *statement = nil;
const char *dbpath = [databasePath UTF8String];
if (sqlite3_open(dbpath, &remindersDB) == SQLITE_OK && textField.text != nil)
{
if (self.navigationItem.rightBarButtonItem.title == #"Save" && [textField.text length] !=0 && [textField1.text length] !=0 && [textField2.text length] !=0 && [textField3.text length] !=0 && [textField4.text length] !=0)
{
NSLog(#"am in the save loop");
if (smsValue == 0)
{
NSString *insertSQL = [NSString stringWithFormat:#"INSERT INTO reminders(name,event,date,bfr,grp,val,sms) VALUES (\"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\")", textField.text, textField1.text,textField2.text,textField3.text,textField4.text,isSelected,selectedVal];
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(remindersDB, insert_stmt, -1, &statement, NULL);
}
else if (smsValue == 1)
{
NSString *insertSQL = [NSString stringWithFormat:#"INSERT INTO reminders(name,event,date,bfr,grp,val,sms,num,bod) VALUES (\"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\", \"%#\")", textField.text, textField1.text,textField2.text,textField3.text,textField4.text,isSelected,selectedVal,textField5.text,textView.text];
textField5.text = reminderInstance.number;
textView.text = reminderInstance.msgBody;
const char *insert_stmt = [insertSQL UTF8String];
sqlite3_prepare_v2(remindersDB, insert_stmt, -1, &statement, NULL);
}
if (sqlite3_step(statement) == SQLITE_DONE)
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"\nReminder Saved" message:nil delegate:nil cancelButtonTitle:nil otherButtonTitles:nil,nil];
[alert show];
[alert dismissWithClickedButtonIndex:0 animated:YES];
[alert release];
}
else
{
UIAlertView *alert = [[UIAlertView alloc]initWithTitle:#"Alert" message:#"Reminder not saved" delegate:self cancelButtonTitle:#"Ok" otherButtonTitles:nil];
[alert show];
[alert release];
}
}
}
}
I took another view controller with table view where I have populated a table view to view all the records that are being saved and upon selection we take him/her to the controller page that contains form i.e. populated with all the values.So far I have been successful in passing all the values using:
1.The following code in form controller page:
-(id) initWithReminder:(ReminderClass *)aReminder
{
if ( (self=[super init]) )
{
self.reminderInstance = aReminder;
}
return self;
}
2.The following parts of code in display controller:
-(void)loadReminders
{
// setup the reminders array
self.array = [[NSMutableArray alloc] init];
//Retrieve the values of database
const char *dbpath = [self.databasePath UTF8String];
sqlite3_stmt *statement;
if (sqlite3_open(dbpath, &remindersDB) == SQLITE_OK)
{
NSString *querySQL = [NSString stringWithFormat:#"SELECT * FROM reminders"];
const char *query_stmt = [querySQL UTF8String];
if (sqlite3_prepare_v2(self.remindersDB ,query_stmt , -1, &statement, NULL) == SQLITE_OK)
{
while (sqlite3_step(statement) == SQLITE_ROW)
{
ReminderClass *loadedReminder = [[ReminderClass alloc] init];
loadedReminder.reminderID = sqlite3_column_int(statement, 0);
loadedReminder.Name = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 1)]autorelease];
loadedReminder.Event = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 2)]autorelease];
loadedReminder.Date = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 3)]autorelease];
loadedReminder.numDays = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 4)]autorelease];
loadedReminder.remGroup = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 5)]autorelease];
loadedReminder.selString = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 6)]autorelease];
loadedReminder.smsString = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 7)]autorelease];
NSLog(#"selected value = %#",loadedReminder.smsString);
loadedReminder.number = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 8)]autorelease];
loadedReminder.msgBody = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 9)]autorelease];
NSDateFormatter *dateFormat = [[[NSDateFormatter alloc]init]autorelease];
[dateFormat setDateFormat:#"yyyy-MM-dd HH:mm:ss"];
NSDate *theDate = [dateFormat dateFromString:loadedReminder.Date];
NSString *stringDate = [dateFormat stringFromDate:theDate];
loadedReminder.Date = stringDate;
NSLog(#"Date = %#",loadedReminder.Date);
[self.array addObject:loadedReminder];
[loadedReminder release];
}
sqlite3_finalize(statement);
}
sqlite3_close(self.remindersDB);
}
}
Now what is happening is since I have the table view in display controller with 2 containing fields except that are linked to sms state and one with all the fields filled.When I select the view controller it is crashing at line "loadedReminder.number":
* Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '* -[NSPlaceholderString initWithUTF8String:]: NULL cString'
when I remove loadedReminder.number and loadedReminder.msgBody,we can view the table(controller page) no crash problem what so ever...Upon selection of table view cell I am doing the following:
-(void)tableView:(UITableView *)atableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ReminderClass *rem = [self.array objectAtIndex:indexPath.section];
// Instantiate your detail/editor view controller,
// and pass in the ReminderClass object to be edited.
ERAddReminderViewController *rdvc = [[[ERAddReminderViewController alloc]initWithReminder:rem]autorelease];
[self.navigationController pushViewController:rdvc animated:YES];
rdvc.navigationItem.rightBarButtonItem.title = #"Edit";
}
Now I can see all the values properly populated in fields,except the problem with switch.Because it is saving properly,but the switch is always in off state,the state set to default as I have already said during filling the form and saving it (if user selects it and fills the last 2 fields also) to save it(record).
Sorry for this huge description,just wanted to make it detailed,so that any one can understand what my issue is,I have made several searches.But unable to achieve the task.
Can any one please suggest me a way of how to save the switch state in database and then populate the same when loading records from database sqlite.
Thanks every one in advance :)
I found out the solution for it,i.e. use an NSString and assign string value i.e. the retrieved state values that were added to the array.Let me explain this in detail:
In Add Reminder page,take an NSString let's say currentState,now come back to where the saved reminders are viewed,take an array named "stateValues" and add the state values to that array i.e.:
loadedReminder.smsState = [[[NSString alloc]initWithUTF8String:(const char *) sqlite3_column_text(statement, 7)]autorelease];
[stateValues addObject:loadedReminder.smsState];
Now in did select row at index path,where we are navigating to add reminder page for editing or modifying the existing values of reminder,do this:
-(void)tableView:(UITableView *)atableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
ReminderClass *rem = [self.array objectAtIndex:indexPath.section];
NSLog(#" switch state in did : %#",[stateValues objectAtIndex:indexPath.section]);
ERAddReminderViewController *rdvc = [[[ERAddReminderViewController alloc]initWithReminder:rem]autorelease];
rdvc.currentState = [stateValues objectAtIndex:indexPath.section];
}
We have successfully set the values to current state,now get back to add reminder page to set the state of switch,i.e. in viewDidLoad method do the following:
-(void)viewDidLoad
{
if ([currentState isEqualToString:#"0"])
{
[smsSwitch setOn:NO animated:NO];
}
else if([currentState isEqualToString:#"1"])
{
[smsSwitch setOn:YES animated:YES];
}
}
That's it,we have now set the state of switch properly by proper access of values that were saved for all consecutive reminders.
Hope it helps.Thank you!

iphone: how to display sqlite data from diff. statement of query in diff. view?

I was able to get a list of title of the books (tableview) and when i select the book i would like to push to the new view of the details of the books. Do i do it in titleView class 'didSelectRow' or in DetailView class 'viewWillAppear' and if so what exactly do I have to put to get the statement, 3 or contentInfo?
Database Class
(NSArray *) itemsByAuthorID:(NSInteger)authorID {
NSMutableArray *retval = [[NSMutableArray alloc] init];
NSString *query;
code....
query = [NSString stringWithFormat:#"select * from books where books.author_id = '%i'", authorID];
}
code...
sqlite3_stmt *statement;
if (sqlite3_prepare_v2(_database, [query UTF8String], -1, &statement, nil) == SQLITE_OK){
while (sqlite3_step(statement) == SQLITE_ROW) {
int itemID = sqlite3_column_int(statement, 0);
int authorID = sqlite3_column_int(statement, 1);
char *nameChars = (char *) sqlite3_column_text(statement, 2);
char *itemContent = (char *) sqlite3_column_text(statement, 3);
NSString *contentTitle = [[NSString alloc] initWithUTF8String:nameChars];
NSString *contentInfo = [[NSString alloc] initWithUTF8String:itemContent];
Item *info = [[Item alloc] initWithItemID:itemID authorID:authorID contentTitle:(NSString *)contentTitle contentInfo:contentInfo];
[retval addObject:info];
}
sqlite3_finalize(statement);
}
return retval;
You can create a private class for Book and retrive data from database for all books in array of Book.
Then after when didSelectRow is called only pass object of Book as parameter and show details in Detail view.

Sqlite3 Fails Unless I Compile Without Optimization But Only On iOS 3.1.3

I have a very odd problem. My sqlite use in my project which has been working for a while has now stopped working on Xcode 4 compiled code, but only on devices with iOS3.1.3. It fails to return records, but if I turn off code optimization it works perfectly.
Does anyone know what may be the cause of this or has experienced similar issues.
Thanks
Rael
// get word from database
NSString *query = [[NSString alloc] initWithFormat:#"select kana_word, kanji_word, word_type_name, word_subtype_name, custom_category_name, kana_index, dictionary_id from dictionary join word_type on word_type.word_type_id=dictionary.word_type_id join word_subtype on word_subtype.word_subtype_id=dictionary.word_subtype_id join custom_category on custom_category.custom_category_id=dictionary.custom_category_id where kana_index=%d", inKanaIndex];
sqlite3_stmt *statement;
NSLog(#"%#", query);
const char *cQuery = [query UTF8String];
if (sqlite3_prepare_v2(jmwDb, cQuery, -1, &statement, nil) != SQLITE_OK) {
char *errMessage;
errMessage = (char*)sqlite3_errmsg(jmwDb);
sqlite3_finalize(statement);
[query release];
return nil;
}
// build a word object
int kanji_key;
if (sqlite3_step(statement) == SQLITE_ROW) {
// create new word
self.kana = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 0)];
self.kanji = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 1)];
self.wordType = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 2)];
self.wordSubType = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 3)];
self.customCategory = [NSString stringWithUTF8String:(char*)sqlite3_column_text(statement, 4)];
self.kanaIndex = sqlite3_column_int(statement, 5);
kanji_key = sqlite3_column_int(statement, 6);
self.dictionaryId = kanji_key;
}
else {
sqlite3_finalize(statement);
[query release];
return nil;
}

how to get absolute last 7 days data, instead of last 7 records in SQLite iPhones

]i have this graph that shows the last 7 records from my sqlite database, it works.
but i will like to know the absolute last 7 days.
this is my codes
if ([appDelegate.drinksOnDayArray count] >=7)
{
drunked = 7;
}
else {
drunked = [appDelegate.drinksOnDayArray count];
}
if (drunked !=0)
{
if (drunked<7) {
for (int i=drunked; i<7; i++) {
//DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i-1];
NSString * dayString= [NSString stringWithFormat:#"Nil"];//[NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];//X label for graph the day of drink.
}
}
for(int i=drunked; i>0; i--)
{
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i-1];
NSString * dayString= [NSDate stringForDisplayFromDateForChart:drinksOnDay.dateConsumed];
[dayArray addObject:dayString];//X label for graph the day of drink.
drinksOnDay.isDetailViewHydrated = NO;
[drinksOnDay hydrateDetailViewData];
NSNumber *sdNumber = drinksOnDay.standardDrinks; // pass value over to Standard Drink Numbers
//[sdArray addObject: sdNumber];
float floatNum = [sdNumber floatValue]; // convert sdNumber to foat
[sdArray addObject:[NSNumber numberWithFloat:floatNum]];//add float Value to sdArray
}
//Get max value using KVC
fMax = [[sdArray valueForKeyPath:#"#max.floatValue"] floatValue];
//Ceiling the max value
imax = (int)ceilf(fMax);
//Odd check to make even by checking right most bit
imax = (imax & 0x1) ? imax + 1 : imax;
NSMutableArray *array = [NSMutableArray arrayWithCapacity:(imax / 2) + 1];
//Assuming all numbers are positive
for(int i = 0; i <= imax; i +=2)
{
[array addObject:[NSString stringWithFormat:#"%d", i]];
}
NSLog(#"Array Value %#", array);
NSLog(#"Day Array%#", dayArray);
NSString *sData[drunked];// = malloc(7 * sizeof(NSString *));
for (int i=0; i<drunked; i++)
{
DayOfDrinks *drinksOnDay = [appDelegate.drinksOnDayArray objectAtIndex:i];
sData[i] = [NSString stringWithFormat:#"%#",drinksOnDay.standardDrinks];
}
NSLog(#"sdArray %#",sdArray);
if (drunked<7) {
for (int i=drunked; i<7; i++) {
sData[i]=[NSString stringWithFormat:#"0"];
}
}
my sqlite statement
- (void) hydrateDetailViewData {
//If the detail view is hydrated then do not get it from the database.
if(isDetailViewHydrated) return;
self.standardDrinks = [NSDecimalNumber zero];
NSDecimalNumber *decimal = [NSDecimalNumber zero];
if(detailStmt == nil) {
const char *sql = "SELECT volume, percentage FROM consumed WHERE DATE(datetime) = ?";
if(sqlite3_prepare_v2(database, sql, -1, &detailStmt, NULL) != SQLITE_OK)
NSAssert1(0, #"Error while creating detail view statement. '%s'", sqlite3_errmsg(database));
}
sqlite3_bind_text(detailStmt, 1, [[NSDate stringFromDate:self.dateConsumed withFormat:#"yyyy-MM-dd"] UTF8String], -1, SQLITE_TRANSIENT);
static NSDecimalNumberHandler* roundingBehavior = nil;
if (roundingBehavior == nil) {
roundingBehavior =
[[NSDecimalNumberHandler alloc] initWithRoundingMode:NSRoundPlain scale:1 raiseOnExactness:NO raiseOnOverflow:NO raiseOnUnderflow:NO raiseOnDivideByZero:NO];
}
while(sqlite3_step(detailStmt) == SQLITE_ROW) {
double volumeDN = sqlite3_column_double(detailStmt, 0);
double percentageDN = sqlite3_column_double(detailStmt, 1);
double drinks = ((volumeDN/1000) * percentageDN);
NSDecimalNumber *drinksDec = [[NSDecimalNumber alloc] initWithDouble:drinks];
NSDecimalNumber *countryRate = [[NSDecimalNumber alloc] initWithDouble:0.789];
decimal = [decimal decimalNumberByAdding:[drinksDec decimalNumberByMultiplyingBy:countryRate]];
//NSLog([NSString stringWithFormat:#"Standard Drinks - %#", self.standardDrinks]);
}
self.standardDrinks = [decimal decimalNumberByRoundingAccordingToBehavior:roundingBehavior];
//Reset the detail statement so it can be used again without preparing the statement again.
sqlite3_reset(detailStmt);
//Set isDetailViewHydrated as YES, so we do not get it again from the database.
isDetailViewHydrated = YES;
}
+ (void) getInitialDataToDisplay:(NSString *)dbPath {
DrinkTabsAndNavAppDelegate *appDelegate = (DrinkTabsAndNavAppDelegate *)[[UIApplication sharedApplication] delegate];
if (sqlite3_open([dbPath UTF8String], &database) == SQLITE_OK) {
const char *sql = "SELECT DATE(datetime) FROM consumed GROUP BY DATE(datetime) ORDER BY datetime DESC";
sqlite3_stmt *selectstmt;
if(sqlite3_prepare_v2(database, sql, -1, &selectstmt, NULL) == SQLITE_OK) {
while(sqlite3_step(selectstmt) == SQLITE_ROW) {
NSString *dateDrunk = [NSString stringWithUTF8String:(char *)sqlite3_column_text(selectstmt, 0)];
NSDate *theDate = [NSDate dateFromString:dateDrunk withFormat:#"yyyy-MM-dd"];
DayOfDrinks *drinkDayObj = [[DayOfDrinks alloc] initWithDateConsumed:theDate];
[drinkDayObj hydrateDetailViewData];
//NSLog([NSDate stringFromDate:drinkDayObj.dateConsumed withFormat:#"yyyy-MM-dd"]);
[appDelegate.drinksOnDayArray addObject:drinkDayObj];
[drinkDayObj release];
}
}
}
else
sqlite3_close(database); //Even though the open call failed, close the database connection to release all the memory.
}
Without going through those blocks of code, I'll hazard a guess here:
SELECT * FROM CONSUMED WHERE DATE BETWEEN ? AND ?
Set up a date 7 days ago (7*24*60*60*1000 milliseconds ago), as well as now, and bind those to the question marks.

Problem getting data from SQLite3 on iPhone

I've been trying to return data from a table after already having accessed two before it, but in this case it get's into the while statement but does not assign any values as everything is set to null.
The code is:
NSMutableArray *all_species = [[NSMutableArray alloc] init];
sqlite3 *db_species;
int dbrc_species;
Linnaeus_LiteAppDelegate *appDelegate = (Linnaeus_LiteAppDelegate*) [UIApplication sharedApplication].delegate;
const char* dbFilePathUTF8 = [appDelegate.dbFilePath UTF8String];
dbrc_species = sqlite3_open (dbFilePathUTF8, &db_species);
if (dbrc_species) {
return all_species;
}
sqlite3_stmt *dbps_species;
const char *queryStatement = "SELECT species_id, species_name, species_latin, species_genus FROM \
linnaeus_species;";
if (sqlite3_prepare_v2 (db_species, queryStatement, -1, &dbps_species, NULL) == SQLITE_OK) {
sqlite3_bind_int(dbps_species, 1, [the_species_id intValue]);
while (sqlite3_step(dbps_species) == SQLITE_ROW) {
Species *species = [[Species alloc] init];
NSLog(#"%#", sqlite3_column_int(dbps_species, 0));
[species setSpecies_id:[[NSNumber alloc] initWithInt:sqlite3_column_int(dbps_species, 0)]];
char *new_name = (char *) sqlite3_column_text(dbps_species, 1);
[species setSpecies_name:nil];
if (new_name != NULL) {
[species setSpecies_name:[NSString stringWithUTF8String:(char *) sqlite3_column_text(dbps_species, 1)]];
}
char *new_latin = (char *) sqlite3_column_text(dbps_species, 2);
[species setSpecies_latin:nil];
if (new_latin != NULL) {
[species setSpecies_latin:[NSString stringWithUTF8String:(char *) sqlite3_column_text(dbps_species, 2)]];
}
[species setSpecies_genus:[NSNumber numberWithInt:sqlite3_column_int(dbps_species, 3)]];
[species setEdited:0];
[all_species addObject:species];
[species release];
}
sqlite3_finalize(dbps_species);
}
else {
sqlite3_close(db_species);
}
I've also tried using NSLog(#"Data: %#", sqlite3_column_text(dbps_species, 1)); and it causes a EXC_BAD_ACCESS error which suggests it could be memory related but I can't see why.
NSLog(#"Data: %#", sqlite3_column_text(dbps_species, 1));
Will cause EXC_BAD_ACCESS because the result of sqlite3_column_text is a C string (char*), not an NSString*. To print C strings you need the %s format specifier:
NSLog(#"Data: %s", sqlite3_column_text(dbps_species, 1));
Also, don't waste time to call sqlite3_column_text twice, e.g.
char *new_name = (char *) sqlite3_column_text(dbps_species, 1);
[species setSpecies_name:nil];
if (new_name != NULL) {
[species setSpecies_name:[NSString stringWithUTF8String:new_name]];
}
You could also try using the FMDB classes. These make using sqlite a LOT easier.
http://gusmueller.com/blog/archives/2008/03/fmdb_for_iphone.html