Swift数组字典存储异常:19条数据仅2条存入数据库,控制台全反馈成功
这种情况确实挺闹心的——明明控制台全喊着“成功”,数据库里却只有两条数据,大概率是代码里藏着没注意到的细节坑。我给你梳理几个最可能的方向,你可以逐一排查:
1. 没捕获数据库操作的真实错误,控制台输出是“假成功”
很多时候我们会下意识在循环里直接打印“插入成功”,但根本没去检查数据库操作是否真的成功。比如如果后面的17条数据触发了主键冲突、非空约束违反,数据库其实已经拒绝插入了,但你的代码没捕获这个错误,还是照常输出成功。
修正方法:给数据库操作加上完整的do-catch错误处理,把成功输出放在do块里,失败时打印具体错误信息:
// 假设用Core Data举例 for dict in yourDataArray { let entity = NSEntityDescription.entity(forEntityName: "YourTable", in: context)! let newRecord = NSManagedObject(entity: entity, insertInto: context) // 映射字典字段到模型 newRecord.setValue(dict["id"], forKey: "id") newRecord.setValue(dict["name"], forKey: "name") // ... 其他字段映射 do { try context.save() print("数据 \(dict["id"]) 插入成功") } catch { print("数据 \(dict["id"]) 插入失败:\(error.localizedDescription)") // 可以打印更详细的错误信息,比如error.userInfo } }
如果是用SQLite的话,执行插入语句后要检查返回的错误码,别直接默认成功。
2. 主键/唯一约束冲突
如果你的数据库表设置了主键(比如id)或者唯一索引,后面的17条数据可能和前两条的主键值重复了。数据库遇到这种情况会直接跳过插入,但如果没捕获错误,你根本不知道发生了什么。
排查方法:
- 先检查数据库表的结构,确认主键/唯一约束的字段;
- 打印所有字典的主键字段值,看看是不是有重复的情况。
3. 循环中复用了同一个数据对象实例
比如在Core Data操作里,如果你把创建NSManagedObject的代码放在循环外面,每次循环只是修改同一个对象的属性,那最后你其实只是不断更新同一个记录,而不是插入新记录。比如这种错误写法:
// 错误:循环外创建对象,循环内重复修改 let entity = NSEntityDescription.entity(forEntityName: "YourTable", in: context)! let newRecord = NSManagedObject(entity: entity, insertInto: context) for dict in yourDataArray { newRecord.setValue(dict["id"], forKey: "id") // ... 修改其他属性 try context.save() // 每次都是更新同一个对象 }
正确做法:把对象创建的代码放到循环内部,每次循环都生成新的实例:
for dict in yourDataArray { let entity = NSEntityDescription.entity(forEntityName: "YourTable", in: context)! let newRecord = NSManagedObject(entity: entity, insertInto: context) newRecord.setValue(dict["id"], forKey: "id") // ... 其他字段映射 } // 批量保存(比每次循环save更高效) do { try context.save() print("所有数据批量保存成功") } catch { print("批量保存失败:\(error)") }
4. 字典键名和数据库字段不匹配
如果后面的17个字典里,某些必填字段的键名写错了(比如数据库字段是userName,字典里是username),导致这些字段没有被赋值,触发了非空约束,数据库拒绝插入,但代码没捕获错误。
排查方法:把字典的键和数据库字段逐一比对,或者在映射的时候打印每个字段的赋值结果,确认有没有空值的情况。
先从添加错误捕获开始吧,拿到真实的错误信息,大部分问题都能迎刃而解!
内容的提问来源于stack exchange,提问作者Luca Milanesi

