Objective-C下保存AttributedString到SQLite3的blob字段报错如何解决?
问题根因
- 直接使用
stringWithFormat拼接SQL语句是语法错误:NSData类型的二进制数据无法直接拼接为SQL字符串的合法值,导致SQL语法错误(错误码1对应SQLITE_ERROR,通常为语法非法) - 原代码执行成功的else分支中存在递归调用
[self saveAttributedItemNote:item],会触发死循环,必须删除。
正确存储实现
使用绑定参数的方式处理Blob类型写入,完整方法实现如下:
- (NSString *)saveAttributedItemNote:(MMItem *)item{ NSString *errorMessage = @"Error"; if (!item || !item.notesAttributed) { return errorMessage; } sqlite3_stmt *stmt = nil; // 使用?作为参数占位符,不需要手动拼接值 const char *sql = "UPDATE Item set noteAttributed = ? WHERE itemID = ?"; if ([self openDB]) { // 预处理SQL语句 int prepareResult = sqlite3_prepare_v2(db, sql, -1, &stmt, NULL); if (prepareResult == SQLITE_OK) { // 绑定第一个参数(占位符索引从1开始):Blob类型数据 // 参数说明:预处理语句、索引、数据指针、数据长度、内存释放策略(SQLITE_TRANSIENT表示SQLite会自动拷贝数据,不需要外部管理) sqlite3_bind_blob(stmt, 1, item.notesAttributed.bytes, (int)item.notesAttributed.length, SQLITE_TRANSIENT); // 绑定第二个参数:itemID sqlite3_bind_int(stmt, 2, (int)item.itemID); // 执行SQL int stepResult = sqlite3_step(stmt); if (stepResult == SQLITE_DONE) { errorMessage = @"OK"; } } // 释放预处理语句资源 sqlite3_finalize(stmt); sqlite3_close(db); } return errorMessage; }
读取富文本补充说明
读取时也需要通过列索引获取Blob数据再解档,核心代码示例:
// 假设已经执行查询语句拿到stmt,Blob字段的列索引为2 NSData *attributedData = [[NSData alloc] initWithBytes:sqlite3_column_blob(stmt, 2) length:sqlite3_column_bytes(stmt, 2)]; NSError *unarchiveError = nil; NSAttributedString *attributedText = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSAttributedString class] fromData:attributedData error:&unarchiveError];
内容的提问来源于stack exchange,提问作者Paul
相关产品推荐
相关产品推荐

