从SQLite数据库中获取UITableView中的NULL值

时间:2015-06-04 17:09:12

标签: ios objective-c cocoa-touch sqlite

程序正在运行,没有问题 我可以看到数据库被打开了 当我向应用添加项目时,它会在 UITableView

中显示为 NULL

我有测试每个动作的单元测试:创建,更新,删除和计数 这些全部通过

以下是我的单元测试:

- (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(@" ");
}

这是创建检索更新删除代码

#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

以下是执行所有操作的代码

添加商品

- (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");

}

删除项目

- (IBAction)deleteToDoItem:(id)sender {
    NSLog(@"Deleting ToDoItem");

    [self.view endEditing:YES];

}

更新项目

- (IBAction)updateToDoItem:(id)sender {
    NSLog(@"updatingToDoItem: Updating ToDoItem");
    toDoItemObject.todoitem = toDoItem.text;
}

填充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;
}

我正在试图找出为什么我的价值观会得到NULL 当我查看数据库时,我实际上看不到表中的任何实体

这是否意味着它实际上没有更新?我对此感到有些困惑。

修改

我手动更新了数据库。我注意到它没有被阅读。我甚至更换了xcode显示正在阅读的数据库。仍然没有。

当使用归档运行时,它运行良好。显然不同的持久化数据方式。

修改

似乎持久化数据实际上是可行的,但出于某种原因,NULL正在插入数据库中。我尝试编辑数据库以查看表是否会重新加载并获取编辑后的值。它似乎没有工作

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

已加载应用 保存新项目后 查看商品时

1 个答案:

答案 0 :(得分:1)

todoitem.todoitemtodoitem.itemname的区别是什么?您可能正在使用todoitem.itemname而不是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;
}

希望这会对你有帮助!

修改

<强> 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;
}

最后,您应该使用init而不是ToDoItemSvcSQLite内的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));
    }
}

并在dealloc内注释此行:

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

再次编辑:

您似乎更改了identifierenter image description here enter image description here

您应该使用viewToDoItem

if ([segue.identifier isEqualToString:@"viewToDoItem"]) {

然后:

// SecondViewController.m
#import "ToDoItemSvcSQLite.h"

- (IBAction)updateToDoItem:(id)sender {
    NSLog(@"updatingToDoItem: Updating ToDoItem");
    toDoItemObject.itemname = toDoItem.text;
    [[ToDoItemSvcSQLite new] updateToDoItem:toDoItemObject];
}