将图像保存到数据库并从服务器加载

时间:2013-08-22 09:16:41

标签: ios iphone image sqlite save

我将图像存储在服务器中。然后我获取图像并通过图像URL保存到db1.sqlite文件。图像像URL一样保存到db1.sqlite文件中。如何显示保存的URL中的图像。具有imageURL路径的product_image。

代码:

sqlite表结构:

CREATE TABLE "product" ("id" INTEGER PRIMARY KEY  NOT NULL , "cat_id" INTEGER NOT NULL , "product_image" VARCHAR NOT NULL , "order_by" INTEGER NOT NULL )

插入代码:

const char *sqlInsert = [[NSString stringWithFormat:@"insert into product (id, cat_id,product_image,order_by) values ('%@','%@','%@','%@')", [tuser objectForKey:@"id"], [tuser objectForKey:@"cat_id"],[tuser objectForKey:@"product_image"],[tuser objectForKey:@"order_by"]] cStringUsingEncoding:NSUTF8StringEncoding];

NSLog(@"product insert %s", sqlInsert);

if(sqlite3_prepare_v2(database, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
    NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));

if(SQLITE_DONE != sqlite3_step(addStmt))
    NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));

图片抓取:

NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory,NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
//NSLog(@"docs dir is %@", documentsDirectory);

NSString *path = [documentsDirectory stringByAppendingPathComponent:@"db1.sqlite"];
//NSLog(@"filepath %@",path);

mArray = [[NSMutableArray alloc]init];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK) {

    const char *sql = "SELECT id,cat_id,product_image FROM product order by order_by";

    NSLog(@"sql is %s",sql);

    sqlite3_stmt *statement;
    //  int catID = 0;
    if (sqlite3_prepare_v2(database, sql, -1, &statement, NULL) == SQLITE_OK) {
        // We "step" through the results - once for each row.
        while (sqlite3_step(statement) == SQLITE_ROW) {

            int length = sqlite3_column_bytes(statement, 2);
            NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 2) length:length];

            UIImage *image = [UIImage imageWithData:imageData];

            [mArray addObject:image];

            [image release];
        }
    }
    sqlite3_finalize(statement);
}
else {
    sqlite3_close(database);
    NSAssert1(0, @"Failed to open database with message '%s'.", sqlite3_errmsg(database));
    // Additional error handling, as appropriate...
}

1 个答案:

答案 0 :(得分:1)

离线与您聊天,我发现product_image不是NSData。 (我之后错误地推断出sqlite3_column_blob的存在,你试图存储二进制数据,但实际情况并非如此。)显然product_image是包含URL的字符串。所以将它存储为字符串。永远不要在SQL语句中使用stringWithFormat,而是将sqlite3_bind_xxx函数与?占位符一起使用,例如:

const char *sqlInsert = "insert into product (id, cat_id, product_image, order_by) values (?, ?, ?, ?)";

if (sqlite3_prepare_v2(database, sqlInsert, -1, &addStmt, NULL) != SQLITE_OK)
    NSAssert1(0, @"Error while creating add statement. '%s'", sqlite3_errmsg(database));

if (sqlite3_bind_int(addStmt, 1, [[tuser objectForKey:@"id"] intValue]) != SQLITE_OK)
    NSAssert1(0, @"Error binding 1. '%s'", sqlite3_errmsg(database));

if (sqlite3_bind_int(addStmt, 2, [[tuser objectForKey:@"cat_id"] intValue]) != SQLITE_OK)
    NSAssert1(0, @"Error binding 2. '%s'", sqlite3_errmsg(database));

if (sqlite3_bind_text(addStmt, 3, [[tuser objectForKey:@"product_image"] UTF8String], -1, NULL) != SQLITE_OK)
    NSAssert1(0, @"Error binding 3. '%s'", sqlite3_errmsg(database));

if (sqlite3_bind_int(addStmt, 4, [[tuser objectForKey:@"order_by"] intValue]) != SQLITE_OK)
    NSAssert1(0, @"Error binding 4. '%s'", sqlite3_errmsg(database));

if (SQLITE_DONE != sqlite3_step(addStmt))
    NSAssert1(0, @"Error while inserting data. '%s'", sqlite3_errmsg(database));

// don't forget to finalize

sqlite3_finalize(addStmt);

如果这样做,您还必须更改检索图像的代码。例如,您有:

while (sqlite3_step(statement) == SQLITE_ROW) {

    int length = sqlite3_column_bytes(statement, 2);
    NSData *imageData = [NSData dataWithBytes:sqlite3_column_blob(statement, 2) length:length];

    UIImage *image = [UIImage imageWithData:imageData];

    [mArray addObject:image];

    [image release];
}

有几点想法:

  1. [image release]过度释放。 imageWithData返回autorelease个对象,因此您不需要/想要释放它。这种错误可能是灾难性的,所以我建议您通过静态分析器运行代码以帮助识别这些类型的错误(通过从“产品”菜单中选择“分析”,或按命令 + + )。您应该有静态分析器生成的警告。分析仪是识别编程错误的一个非常有用的工具,因此可以利用这个优秀的工具。

  2. 之前的观点没有实际意义,因为你没有在NSData中存储实际的图像,而是在一个字符串中存储一个URL,所以你应该使用{{1而是。

  3. sqlite3_column_textconst char *转换为sqlite3_column_text后,您需要获取该字符串并创建一个网址,例如:

    NSString
  4. 然后,您可以将NSURL *url = [NSURL URLWithString:urlStringFromDatabase]; NSURL类别SDWebImage结合使用,以异步方式检索图像(并执行所有适当的缓存等)

    UIImageView
  5. 并且,冒着重复自己的风险,您的图像检索代码会检查SQLite函数是否返回,例如[imageView setImageWithURL:url placeholderImage:[UIImage imageNamed:@"placeholder.png"]]; ,但如果没有,则表示您没有显示SQLITE_OK。在调试应用程序时始终要看这个。它将在开发/调试中节省数小时。