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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.02 12:15:00