0

Program is running without issue
I can see the database being opened
When I add an item to the app, it shows up as NULL in the UITableView

I have unit tests that test each action: create, update, delete, and count.
These all pass

Here are my unit tests:

- (void)testToDoItemSQLite {
    NSLog(@" ");
    NSLog(@"*** Starting testToDoItemSQLite ***");

    ToDoItemSvcSQLite *todoitemSvc = [[ToDoItemSvcSQLite alloc] init];
    ToDoItem *todoitem = [[ToDoItem alloc] init];
    todoitem.itemname = @"This was created by a unit test";
    [todoitemSvc createToDoItem:todoitem];

    NSMutableArray *todoitems = [todoitemSvc retrieveAllToDoItems];
    NSLog(@"*** number of todoitems: %lu", (unsigned long)todoitems.count);

    todoitem.itemname = @"This was created by a unit test";
    [todoitemSvc updateToDoItem:todoitem];

    [todoitemSvc deleteToDoItem:todoitem];

    NSLog(@"*** Ending testToDoItemSQLite ***");
    NSLog(@" ");
}

This is my create, retrieve, update, and 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 is 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 to create table %s", errMsg);
            }

        }
        else {
            NSLog(@"*** Failed to open database!");
            NSLog(@"*** SQL error: %s\n", sqlite3_errmsg(database));
        }
    }
    return self;
}

- (ToDoItem *) createToDoItem:(ToDoItem *)todoitem {
    sqlite3_stmt *statement;
    NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO 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 * FROM todoitem ORDER BY 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=\"%@\" WHERE 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 FROM todoitem WHERE 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 is the code that is executing all the 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 to figure out why I am getting NULL back for my values.
When I look at the database, I don't actually see any entities in the table

Does this mean its not actually updating? I'm a little confused on this.

EDIT

I manually updated the database. I noticed that its not being read. I even replaced the database that xcode shows it is reading. Still nothing.

When this was running using archiving it worked great. Obviously different way of persisting data.

EDIT

It appears that persisting the data is in fact working but for some reason NULL is being inserted in the database. I tried editing the database to see if the table would reload and pick up the edited value. It didnt seem to work

this is the app when it first runs this is the tableview after entering an item this is the value when you tape on it what is being seen in the database

App loaded After saving a new item When viewing an item

2
  • Show the code that calls these methods and reloads the table view. Commented Jun 5, 2015 at 2:21
  • Added the code you asked to see. Thanks for looking. Commented Jun 5, 2015 at 3:39

1 Answer 1

1

What's the difference of todoitem.todoitem and todoitem.itemname? You may be 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 this will help 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;  // I 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]; // I edited
    return cell;
}

SecondViewController.m

- (void)viewDidLoad {
    [super viewDidLoad];
    // Do any additional setup after loading the view.

    toDoItem.text = toDoItemObject.itemname; // I edited
}

ToDoItemSvcSQLite.m

- (ToDoItem *) updateToDoItem:(ToDoItem *)todoitem {
    NSString *updateSQL = [NSString stringWithFormat: @"UPDATE todoitem SET itemname=\"%@\" WHERE id = %i ", todoitem.itemname, todoitem.id]; // I 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, you 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 is 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 to create table %s", errMsg);
        }

    } else {
        NSLog(@"*** Failed to open database!");
        NSLog(@"*** SQL error: %s\n", sqlite3_errmsg(database));
    }
}

and comments this line inside dealloc:

- (void)dealloc {
//    sqlite3_close(database);
}

EDIT AGAIN:

It seems you changed the identifier: enter image description here enter image description here

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];
}
Sign up to request clarification or add additional context in comments.

13 Comments

It looks like its now not entering a NULL value. Its not updating still and my textfield isnt showing the object nor is it updating.
Can you post your project on GitHub?
Sure Its already up. github.com/martylavender/LittleToDoApp/tree/addingsqlite On a side note, I need to update my viewcontroller to be embedded in a navigation controller and get rid of the navigation bar. I had that done, but i ended up losing the last batch of changes. :) Just an FYI that I realize how I have it running right now is not best practice.
I have tried your project, the problem will be resolved if you updated your code using my suggestion. I will edit my answer that causes it clearly.
Did I miss something on the edits? I'm going to feel stupid if I did.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.