【问题标题】:(Objective C) Save changes in sqlite database(目标 C)在 sqlite 数据库中保存更改
【发布时间】:2013-11-26 01:15:02
【问题描述】:

我正在为我的学校项目创建一个应用程序,该应用程序必须将数据写入我的 sqlite 数据库。只要应用程序处于活动状态,它就可以工作,但是一旦应用程序关闭,我添加的数据就消失了,当我想读取这些数据时,这将无法正常工作。我包括了我的loadDatasaveData 方法。这两个函数中的两个数据库路径是相同的,所以我不是在其他地方写我的数据。我真的找不到解决方案或问题。我什至在我的输出中得到了插入成功,所以插入成功了。

- (void) saveData:(id)sender{
    NSString *sqldb = [[NSBundle mainBundle] pathForResource:@"PXLate" ofType:@"sqlite3"];
    sqlite3_stmt *stmt;
    NSString *queryInsert = @"INSERT INTO assignments (name, lesson, dueDate, notification, start, at) VALUES ('abc','abc', 'abc', 1, 'abc', 'abc')";
    NSLog(@"%@",sqldb);

    NSLog(@"%@",queryInsert);
    if(sqlite3_open([sqldb UTF8String], &_PXLate) == SQLITE_OK)
    {
        sqlite3_prepare_v2(_PXLate, [queryInsert UTF8String], -1, &stmt, NULL);

        if(sqlite3_step(stmt)==SQLITE_DONE)
        {
            NSLog(@"insert success");
        }
        else
        {
            NSLog(@"insert un success");
            NSAssert1(0, @"Error: failed to prepare statement with message '%s'.", sqlite3_errmsg(_PXLate));
        }

        int success=sqlite3_step(stmt);

        if (success == SQLITE_ERROR)
        {
            NSAssert1(0, @"Error: failed to insert into the database with message '%s'.", sqlite3_errmsg(_PXLate));
            //[_PXLate save:&error];

        }        sqlite3_finalize(stmt);
    }
    sqlite3_close(_PXLate);
}

还有我的loadData 函数

- (void) loadData:(id)sender
{
     //path for database
        NSString *sqldb = [[NSBundle mainBundle] pathForResource:@"PXLate" ofType:@"sqlite3"];
    //check if present
    NSFileManager*fm=[NSFileManager defaultManager];
        NSLog(@"path: %@", sqldb);

    const char *dbpath = [sqldb UTF8String];
    sqlite3_stmt    *statement;

    if (sqlite3_open(dbpath, &_PXLate) == SQLITE_OK)
    {
        NSString *querySQL = [NSString stringWithFormat: @"SELECT * FROM assignments WHERE name='abc'", _label.text];
        const char *query_stmt = [querySQL UTF8String];
        NSLog(@"name");
        NSLog(querySQL);
        int response = sqlite3_prepare_v2(_PXLate, query_stmt, -1, &statement, NULL);
        NSLog(@"response %d", response);

        if (response == SQLITE_OK)
        {
            NSLog(@"name");
            if (sqlite3_step(statement) == SQLITE_ROW)
            {
                NSString *namefield = [[NSString alloc]
                                          initWithUTF8String:
                                          (const char *) sqlite3_column_text(
                                                                             statement, 0)];
                NSLog(@"name:%@", namefield);
                _label.text = namefield;
            } else {
                _label.text = @"Match not found";

            }
            sqlite3_finalize(statement);
        }
        sqlite3_close(_PXLate);
    }
}

【问题讨论】:

标签: ios objective-c c database sqlite


【解决方案1】:

您必须将您的 sqlite 复制到文档目录,然后使用它。示例:

self.databaseName = @"databasename.sqlite";

// Get the path to the documents directory and append the databaseName
NSArray *documentPaths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDir = [documentPaths objectAtIndex:0];

self.databasePath = [[NSString alloc]init];
self.databasePath = [documentsDir stringByAppendingPathComponent:self.databaseName];
[self checkAndCreateDatabase];

以及创建方法:

-(void)checkAndCreateDatabase 
{
   NSFileManager *fileManager = [NSFileManager defaultManager];
   NSString *databasePathFromApp = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:self.databaseName];
   [fileManager copyItemAtPath:databasePathFromApp toPath:self.databasePath error:nil];
}

【讨论】:

  • 我假设您的意思是让checkAndCreateDatabase 检查databasePath 中的文件是否存在,并且仅在该文件不存在时复制。
  • 正确。我认为 copyItemAtPath: 仅在文件不存在时插入。如果我错了,请纠正我。
  • 同意,但我个人更喜欢先检查文档中的文件是否存在,如果不存在则仅尝试复制。这样,您可以更轻松地将已知和可能的情况(不需要复制)与不太可能但仍然可能的真正错误(我们需要复制文件,但尝试的复制操作由于某种原因失败)区分开来。但是你是对的,即使不需要副本,你也可以尝试复制,如果文件已经存在,就让它失败。
【解决方案2】:

几个观察:

  1. 正如 Retterdesdialogs 所说,你应该

    • 检查文档中是否存在数据库;

    • 如果不存在,则从捆绑包复制到文档;和

    • 从 Documents 打开数据库。

    您不应该从捆绑包中打开数据库,因为在设备上该文件夹是只读的。

  2. 在您的INSERT 语句中,您没有检查sqlite3_prepare_v2 的响应,这是一个非常常见的错误来源。如果这不是SQLITE_OK,您应立即登录sqlite3_errmsg,然后再致电sqlite3_step

  3. 您在INSERT 语句中执行了两次sqlite3_step

  4. loadData 中,如果sqlite3_prepare_v2 失败,您将不会记录sqlite3_errmsg。如有任何错误,请始终查看sqlite3_errmsg

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2010-09-26
    • 2012-05-28
    • 1970-01-01
    • 1970-01-01
    • 2011-08-10
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多