You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

为何NSMutableArray数据插入SQLite仅存首组值?求排查

问题分析与修复方案

我帮你拆解下代码里的核心问题,这就是为啥你只能插入前5个元素、或者数据混乱的原因:

现存问题

  • 循环逻辑完全错误:你的lockInfo是每5个元素对应一条数据库记录(比如51974, 0, 2, 15, 1是第一行,51975, 0, 24, 15, 1是第二行),但你现在的循环是逐个元素遍历,相当于尝试插入20条无效记录,而非4条有效记录。
  • 参数绑定索引混乱:你绑定字段时,前三个用了objectAtIndex:i,第四、第五个直接固定用索引3和4,完全没按每组5个元素的对应关系来,只会重复插入前几个元素的内容。
  • 数据类型不匹配:从数组内容看,里面都是数字类型(应该是NSNumber),但你用了sqlite3_bind_text绑定文本类型,这会导致类型转换错误,数据无法正确存入。
  • 错误处理缺失:代码没捕获sqlite3_prepare_v2和sqlite3_step的错误,出问题时根本不知道哪里错了。

修正后的代码

-(void)insertLock:(NSMutableArray *)lockInfo{
    char *error;
    NSString *databasePath = [self dataPath:@"eloqdb.sqlite3"];
    sqlite3 *database;
    
    if (sqlite3_open([databasePath UTF8String], &database) != SQLITE_OK) {
        sqlite3_close(database);
        NSLog(@"Could not open database");
        return; // 打开失败直接终止,避免后续无效操作
    }
    NSLog(@"DB opened");

    NSLog(@"lockInfo content: %@", lockInfo);
    NSLog(@"lockInfo count: %i", lockInfo.count);

    // 每5个元素对应一条记录,循环步长设为5
    for (int i = 0; i < lockInfo.count; i += 5) {
        // 检查剩余元素是否足够组成一条记录,防止数组越界崩溃
        if (i + 4 >= lockInfo.count) {
            NSLog(@"Invalid data: not enough elements at index %d", i);
            continue;
        }

        sqlite3_stmt *statement;
        NSString *SQLInsert = @"INSERT OR REPLACE INTO LOCK_PLAN_CHANGE (ID, FLAG, ITEM_DOOR_ID, KEY_SERIAL, TIMEZONE_ITEM_ID) VALUES (?, ?, ?, ?, ?);";
        
        if (sqlite3_prepare_v2(database, [SQLInsert UTF8String], -1, &statement, nil) != SQLITE_OK) {
            NSLog(@"Failed to prepare SQL: %s", sqlite3_errmsg(database));
            continue;
        }

        // 绑定整数类型参数(假设数组元素是NSNumber)
        sqlite3_bind_int(statement, 1, [[lockInfo objectAtIndex:i] intValue]);
        sqlite3_bind_int(statement, 2, [[lockInfo objectAtIndex:i+1] intValue]);
        sqlite3_bind_int(statement, 3, [[lockInfo objectAtIndex:i+2] intValue]);
        sqlite3_bind_int(statement, 4, [[lockInfo objectAtIndex:i+3] intValue]);
        sqlite3_bind_int(statement, 5, [[lockInfo objectAtIndex:i+4] intValue]);

        if (sqlite3_step(statement) != SQLITE_DONE) {
            NSLog(@"Failed to execute SQL: %s", sqlite3_errmsg(database));
        }

        sqlite3_finalize(statement);
    }

    sqlite3_close(database);
}

关键改动说明

  1. 调整循环步长:把i++改成i += 5,每次循环处理一组5个元素,对应一条数据库记录。
  2. 添加越界防护:避免数组元素数量不是5的倍数时,出现越界崩溃。
  3. 修正绑定索引:每组元素分别对应i、i+1、i+2、i+3、i+4,和数据库字段一一对应。
  4. 改用正确的绑定函数:因为数组里是整数,用sqlite3_bind_int替代sqlite3_bind_text,保证数据类型匹配。
  5. 完善错误日志:用sqlite3_errmsg打印具体错误信息,方便后续排查问题。

内容的提问来源于stack exchange,提问作者astric mobiles

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.12 04:35:20