【问题标题】:Save and retrieve AttributedString to SQLite3将 AttributedString 保存并检索到 SQLite3
【发布时间】:2021-11-21 01:30:06
【问题描述】:

我在 Objective-c 中有一个项目,我试图找到一种方法将属性文本从 UITextView 保存到 SQLite3 表。 我的项目目标操作系统是 12.1。 我正在使用一个名为“MMItem”的对象和一个名为“notesAttributed”的 NSData 属性。 在我的 viewController 类中,我使用 NSKeyedArchiver 将 AttributedText 编码为 NSdata 格式,然后复制到对象属性。

NSData *data = [NSKeyedArchiver archivedDataWithRootObject:self.itemNotes.attributedText requiringSecureCoding:YES error:Nil];
self.item.notesAttributed = data;

然后我在我的模型中调用一个方法来保存对象

NSString *resultStr = [self.meetingModel saveAttributedItemNote:item];

在模型中,我尝试将属性字符串保存到项目表设置中的字段中,类型为“blob”

- (NSString *)saveAttributedItemNote:(MMItem *)item{
NSString *errorMessage;
NSString *sql;
NSInteger result = 0;

if (item) {
    //create blob encoded data for Attributed notes
    NSInteger itemID = item.itemID;
    
    sql = [NSString stringWithFormat:
    @"UPDATE Item set noteAttributed = %@ WHERE itemID = %ld",item.notesAttributed, (long)itemID];
    
    char *err;
    // open DB and save
    if ([self openDB]){
        //NSLog(@"%@", NSStringFromSelector(_cmd));
        result = sqlite3_exec(db, [sql UTF8String], NULL, NULL, &err);
        sqlite3_close(db);
    }
    
    if (result != SQLITE_OK)
    {
        errorMessage = @"Error";
    }
    else
    {
        //NSLog(@"Table updated");
        errorMessage  = @"OK";
        [self saveAttributedItemNote:item];
    }
    
}
item = nil;
return errorMessage;

}

SQL Execute 语句失败并出现错误 1。

我怀疑我打算使用“绑定”而不是 Execute 语句将 blob 插入表中,但我只是找到了如何使用 Objective-c 将所有这些放在一起。 任何帮助都会非常感谢。

【问题讨论】:

  • 一个叫 'MMItem' 的人是从哪里来的?
  • SQLite和NSKeyedArchiver有什么业务?
  • 开放数据库?它来自哪里?
  • MMItem 是一个 NSobject,它包含一个 'Item' 的所有属性,例如 itemID、topicID、itemDescription 等
  • openDB 是我的模型中打开 SQLite DB 的一种方法

标签: objective-c sqlite save blob nsattributedstring


【解决方案1】:

感谢以下帖子iOS SQLite Blob data is saving NULL 我设法得到了一个可行的解决方案。很明显,要将 blob 保存到 SQLite 中,您必须使用带有 sqlite3_bind_blob 的 Prepare 语句将 blob 参数插入到语句中,然后使用 sqlite3_step 来部署它。 然后,这允许字节和长度参数也被传递到语句中,我认为使用我最初尝试的执行方法无法做到这一点。 这是完美运行的代码。

- (NSString *)saveAttributedItemNote:(MMItem *)item{
NSString *errorMessage;

if (item) {
    //create blob encoded data for Attributed notes
    int itemID = (int)item.itemID;
    
    if ([self openDB]) {
        
        const char *insert_stmt = "UPDATE Item set notesAttributed = ? WHERE itemID = ?";
        
        sqlite3_stmt *statement;
        if (sqlite3_prepare_v2(db, insert_stmt, -1, &statement, NULL) == SQLITE_OK) {
            sqlite3_bind_blob(statement, 1, item.notesAttributed.bytes, (int)item.notesAttributed.length, SQLITE_TRANSIENT);
            sqlite3_bind_int(statement, 2, itemID);
            
            if (sqlite3_step(statement) == SQLITE_DONE) {
                errorMessage  = @"OK";
                //update successfull
            }else{
                const char *err = sqlite3_errmsg(db);
                NSString *error = [[NSString alloc] initWithUTF8String:err];
                NSLog(@"Update error ID:%@",error);
                errorMessage = @"Error";
            }
            sqlite3_finalize(statement);
        }else{
            errorMessage = @"Error";
            NSLog(@"Unable to prepare stsement %s: %s",insert_stmt, sqlite3_errmsg(db));
        }
        sqlite3_close(db);
    }

}
item = nil;
return errorMessage;

}

下面的代码然后显示了如何从 sqlite 中检索该字段。第 11 列是 blob。

if (sqlite3_prepare(db, [sql UTF8String], -1, &statement, nil)==SQLITE_OK)
    {
        //NSLog(@"SQL Select OK");
        
        while (sqlite3_step(statement)==SQLITE_ROW) {
            MMItem *item = [[MMItem alloc]init];
            item.itemID = sqlite3_column_int(statement, 0);
            item.topicID = sqlite3_column_int(statement, 1);
            item.sequenceID = sqlite3_column_int(statement, 2);
            char *description = (char *) sqlite3_column_text(statement, 3);
            if(description) item.itemDescription = [[NSString alloc]initWithUTF8String:description];
            char *notes = (char *) sqlite3_column_text(statement, 4);
            if(notes) item.notes = [[NSString alloc]initWithUTF8String:notes];
            char *actionBy = (char *) sqlite3_column_text(statement, 5);
            if(actionBy) item.actionBy = [[NSString alloc]initWithUTF8String:actionBy];
            char *requiredBy = (char *) sqlite3_column_text(statement, 6);
            if (requiredBy) item.requiredBy = [[NSString alloc]initWithUTF8String:requiredBy];
            item.completed = sqlite3_column_int(statement, 7);
            char *proposedBy = (char *) sqlite3_column_text(statement, 8);
            if (proposedBy) item.proposedBy = [[NSString alloc]initWithUTF8String:proposedBy];
            char *secondedBy = (char *) sqlite3_column_text(statement, 9);
            if (secondedBy) item.secondedBy = [[NSString alloc]initWithUTF8String:secondedBy];
            item.carried = sqlite3_column_int(statement, 10);
            NSData *attributedTextData = [[NSData alloc]initWithBytes:sqlite3_column_blob(statement,11) length:sqlite3_column_bytes(statement, 11)];
            item.notesAttributed = attributedTextData;
            
            
            [items addObject:item];
            item = nil;
        }
    }

然后在 ViewController 中,使用以下内容获取 NSData 属性并将其解码为 UITextView (self.itemNotes)

self.itemNotes.attributedText = [NSKeyedUnarchiver unarchivedObjectOfClass:([NSAttributedString class]) fromData:self.item.notesAttributed error:&error];

很奇怪,只是发布问题会导致我找到正确的解决方案。感谢 El Tomato 的帮助。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-11-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-08-25
    • 2011-10-15
    相关资源
    最近更新 更多