ios - Getting NULL value back in UITableView from SQLite database -
program running without issue
can see database being opened
when add item app, shows null in uitableview
i have unit tests test each action: create, update, delete, , count.
these pass
here unit tests:
- (void)testtodoitemsqlite { nslog(@" "); nslog(@"*** starting testtodoitemsqlite ***"); todoitemsvcsqlite *todoitemsvc = [[todoitemsvcsqlite alloc] init]; todoitem *todoitem = [[todoitem alloc] init]; todoitem.itemname = @"this created unit test"; [todoitemsvc createtodoitem:todoitem]; nsmutablearray *todoitems = [todoitemsvc retrievealltodoitems]; nslog(@"*** number of todoitems: %lu", (unsigned long)todoitems.count); todoitem.itemname = @"this created unit test"; [todoitemsvc updatetodoitem:todoitem]; [todoitemsvc deletetodoitem:todoitem]; nslog(@"*** ending testtodoitemsqlite ***"); nslog(@" "); }
this create, retrieve, update, , delete code
#import "todoitemsvcsqlite.h" #import "sqlite3.h" @implementation todoitemsvcsqlite nsstring *databasepath = nil; sqlite3 *database = nil; - (id)init { if ((self = [super init])) { nsarray *documentpaths = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes); nsstring *documentsdir = [documentpaths objectatindex:0]; databasepath = [documentsdir stringbyappendingpathcomponent:@"todoitem.sqlite3"]; if (sqlite3_open([databasepath utf8string], &database) == sqlite_ok) { nslog(@"database open"); nslog(@"database file path: %@", databasepath); nsstring *createsql = @"create table if not exists todoitem (id integer primary key autoincrement, itemname varchar(200))"; char *errmsg; if (sqlite3_exec(database, [createsql utf8string], null, null, &errmsg) !=sqlite_ok) { nslog(@"failed create table %s", errmsg); } } else { nslog(@"*** failed open database!"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } } return self; } - (todoitem *) createtodoitem:(todoitem *)todoitem { sqlite3_stmt *statement; nsstring *insertsql = [nsstring stringwithformat: @"insert todoitem (itemname) values (\"%@\")", todoitem.itemname]; if (sqlite3_prepare(database, [insertsql utf8string], -1, &statement, null) == sqlite_ok) { if (sqlite3_step(statement) == sqlite_done) { todoitem.itemid = sqlite3_last_insert_rowid(database); nslog(@"todoitem added"); } else { nslog(@"*** todoitem not added"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } sqlite3_finalize(statement); } return todoitem; } - (nsmutablearray *) retrievealltodoitems { nsmutablearray *todoitems = [nsmutablearray array]; nsstring *selectsql = [nsstring stringwithformat:@"select * todoitem order itemname"]; sqlite3_stmt *statement; if (sqlite3_prepare_v2(database, [selectsql utf8string], -1, &statement, null) == sqlite_ok) { nslog(@"*** todoitems retrieved"); while (sqlite3_step(statement) == sqlite_row) { int id = sqlite3_column_int(statement, 0); char *itemnamechars = (char *)sqlite3_column_text(statement, 1); todoitem *todoitem = [[todoitem alloc] init]; todoitem.itemid = id; todoitem.itemname = [[nsstring alloc] initwithutf8string:itemnamechars]; [todoitems addobject:todoitem]; } sqlite3_finalize(statement); } else { nslog(@"*** todoitems not retrieved"); nslog(@"*** sql error %s\n", sqlite3_errmsg(database)); } return todoitems; } - (todoitem *) updatetodoitem:(todoitem *)todoitem { nsstring *updatesql = [nsstring stringwithformat: @"update todoitem set itemname=\"%@\" id = %li ", todoitem.itemname, (long)todoitem.itemid]; sqlite3_stmt *statement; if (sqlite3_prepare_v2(database, [updatesql utf8string], -1, &statement, null) == sqlite_ok) { if (sqlite3_step(statement) == sqlite_done) { nslog(@"*** todoitem updated"); } else { nslog(@"todoitem not updated"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } sqlite3_finalize(statement); } return todoitem; } - (todoitem *) deletetodoitem:(todoitem *)todoitem { nsstring *deletesql = [nsstring stringwithformat: @"delete todoitem id = %i",(int) todoitem.itemid]; sqlite3_stmt *statement; if (sqlite3_prepare_v2(database, [deletesql utf8string], -1, &statement, null) == sqlite_ok) { if (sqlite3_step(statement) == sqlite_done) { nslog(@"*** todoitem deleted"); } else { nslog(@"*** todoitem not deleted"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } sqlite3_finalize(statement); } return todoitem; } - (void)dealloc { sqlite3_close(database); } @end
here code executing actions
adds item
- (ibaction)addtodoitem:(id)sender { [self.view endediting:yes]; nslog(@"savetodoitem: adding todoitem"); todoitem *todoitem = [[todoitem alloc] init]; todoitem.todoitem = _todoitem.text; [todoitemsvc createtodoitem:todoitem]; //clears text field on save _todoitem.text = @""; [self.tableview reloaddata]; nslog(@"savetodoitem: todoitem saved"); }
deletes item
- (ibaction)deletetodoitem:(id)sender { nslog(@"deleting todoitem"); [self.view endediting:yes]; }
updates item
- (ibaction)updatetodoitem:(id)sender { nslog(@"updatingtodoitem: updating todoitem"); todoitemobject.todoitem = todoitem.text; }
populates uitableview
- (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { static nsstring *simpletableidentifier = @"todoitemcell"; uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:simpletableidentifier]; if (cell == nil) { cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstyledefault reuseidentifier:simpletableidentifier]; } todoitem *todoitem = [[todoitemsvc retrievealltodoitems] objectatindex:indexpath.row]; cell.textlabel.text = [todoitem description]; return cell; }
i'm trying to figure out why getting null
values.
when @ database, don't see entities in table
does mean not updating? i'm little confused on this.
edit
i manually updated database. noticed not being read. replaced database xcode shows reading. still nothing.
when running using archiving worked great. different way of persisting data.
edit
it appears persisting data in fact working reason null
being inserted in database. tried editing database see if table reload , pick edited value. didnt seem work
app loaded after saving new item when viewing item
what's difference of todoitem.todoitem
, todoitem.itemname
? may using todoitem.itemname
instead of using todoitem.todoitem
:
- (ibaction)addtodoitem:(id)sender { … todoitem.itemname = _todoitem.text; [todoitemsvc createtodoitem:todoitem]; ... } - (ibaction)updatetodoitem:(id)sender { nslog(@"updatingtodoitem: updating todoitem"); todoitemobject.itemname = todoitem.text; } - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { ... todoitem *todoitem = [[todoitemsvc retrievealltodoitems] objectatindex:indexpath.row]; cell.textlabel.text = todoitem.itemname; return cell; }
hope you!
edit:
viewcontroller.m
- (ibaction)addtodoitem:(id)sender { [self.view endediting:yes]; nslog(@"savetodoitem: adding todoitem"); todoitem *todoitem = [[todoitem alloc] init]; todoitem.itemname = _todoitem.text; // edited [todoitemsvc createtodoitem:todoitem]; //clears text field on save _todoitem.text = @""; [self.tableview reloaddata]; nslog(@"savetodoitem: todoitem saved"); } - (uitableviewcell *)tableview:(uitableview *)tableview cellforrowatindexpath:(nsindexpath *)indexpath { static nsstring *simpletableidentifier = @"todoitemcell"; uitableviewcell *cell = [tableview dequeuereusablecellwithidentifier:simpletableidentifier]; if (cell == nil) { cell = [[uitableviewcell alloc] initwithstyle:uitableviewcellstyledefault reuseidentifier:simpletableidentifier]; } todoitem *todoitem = [[todoitemsvc retrievealltodoitems] objectatindex:indexpath.row]; cell.textlabel.text = [todoitem itemname]; // edited return cell; }
secondviewcontroller.m
- (void)viewdidload { [super viewdidload]; // additional setup after loading view. todoitem.text = todoitemobject.itemname; // edited }
todoitemsvcsqlite.m
- (todoitem *) updatetodoitem:(todoitem *)todoitem { nsstring *updatesql = [nsstring stringwithformat: @"update todoitem set itemname=\"%@\" id = %i ", todoitem.itemname, todoitem.id]; // edited sqlite3_stmt *statement; if (sqlite3_prepare_v2(database, [updatesql utf8string], -1, &statement, null) == sqlite_ok) { if (sqlite3_step(statement) == sqlite_done) { nslog(@"*** todoitem updated"); } else { nslog(@"todoitem not updated"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } sqlite3_finalize(statement); } return todoitem; }
finally, instead of using init
inside todoitemsvcsqlite
, should use initialize
:
// todoitemsvcsqlite.m static sqlite3 *database = nil; + (void)initialize { nsarray *documentpaths = nssearchpathfordirectoriesindomains(nsdocumentdirectory, nsuserdomainmask, yes); nsstring *documentsdir = [documentpaths objectatindex:0]; databasepath = [documentsdir stringbyappendingpathcomponent:@"todoitem"]; if (sqlite3_open([databasepath utf8string], &database) == sqlite_ok) { nslog(@"database open"); nslog(@"database file path: %@", databasepath); nsstring *createsql = @"create table if not exists todoitem (id integer primary key autoincrement, itemname varchar(200))"; char *errmsg; if (sqlite3_exec(database, [createsql utf8string], null, null, &errmsg) !=sqlite_ok) { nslog(@"failed create table %s", errmsg); } } else { nslog(@"*** failed open database!"); nslog(@"*** sql error: %s\n", sqlite3_errmsg(database)); } }
and comments line inside dealloc
:
- (void)dealloc { // sqlite3_close(database); }
edit again:
it seems changed identifier
:
you should use viewtodoitem
:
if ([segue.identifier isequaltostring:@"viewtodoitem"]) {
then:
// secondviewcontroller.m #import "todoitemsvcsqlite.h" - (ibaction)updatetodoitem:(id)sender { nslog(@"updatingtodoitem: updating todoitem"); todoitemobject.itemname = todoitem.text; [[todoitemsvcsqlite new] updatetodoitem:todoitemobject]; }
Comments
Post a Comment