我正在数据库中保存图像,还使用av捕获会话创建自定义相机。但随着我在数据库中保存越来越多的图像,它会给出内存警告。
当我停止将图像保存到数据库时,该应用程序工作正常,为什么会发生?是否因为数据库的大小增加而发生?
当前代码:
-(void)insert
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"dbsqlite.sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
////////\\
for (jk=0; jk<[globalvalue count];jk++)
{
NSData *imgData = UIImagePNGRepresentation((UIImage *)[globalvalue objectAtIndex:jk]);
const char *query = "insert into color(img) values (?)";
sqlite3_stmt *searchStatement2;
if (sqlite3_prepare_v2(database,query, -1, &searchStatement2, NULL) == SQLITE_OK)
{
sqlite3_bind_blob(searchStatement2,1, [imgData bytes], [imgData length], NULL);
if (sqlite3_step(searchStatement2) == SQLITE_DONE)
{
NSLog(@"saved");
}
//
// while (sqlite3_step(searchStatement2) == SQLITE_ROW)
// {
// NSString *name2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement2, 0)];
// NSString *category2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement2, 1)];
// NSLog(@"%@ is a %@ color", name, category);
//
//
// }
}
sqlite3_finalize(searchStatement2);
}
}
[[[UIAlertView alloc]initWithTitle:@"alert" message:@"your query saved" delegate:nil cancelButtonTitle:@"cancel" otherButtonTitles: nil] show];
sqlite3_close(database);
}
- (void)makeDBCopyAsNeeded
{
BOOL success;
NSFileManager *fileManager = [NSFileManager defaultManager];
NSError *error;
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *writableDBPath = [documentsDirectory stringByAppendingPathComponent:@"dbsqlite.sqlite"];
success = [fileManager fileExistsAtPath:writableDBPath];
if (success)
{
return;
}
NSString *defaultDBPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"dbsqlite.sqlite"];
success = [fileManager copyItemAtPath:defaultDBPath toPath:writableDBPath error:&error];
if (!success)
{
NSAssert1(0, @"Failed to create writable database file with message '%@'.", [error localizedDescription]);
}
}
-(void)readFromDatabase
{
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *path = [documentsDirectory stringByAppendingPathComponent:@"dbsqlite.sqlite"];
if (sqlite3_open([path UTF8String], &database) == SQLITE_OK)
{
const char *sqlStatement="select img,rowID from color";
sqlite3_stmt *compiledStatement;
if(sqlite3_prepare_v2(database, sqlStatement, -1, &compiledStatement, NULL)==SQLITE_OK)
{
while (sqlite3_step(compiledStatement)==SQLITE_ROW)
{
NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(compiledStatement,0) length:sqlite3_column_bytes(compiledStatement,0)];
if(data == nil)
NSLog(@"No image found.");
else
{
UIImage *personImage= [UIImage imageWithData:data];
NSString *rowid1=[NSString stringWithFormat:@"%d", sqlite3_column_int(compiledStatement,1)];
[rowid addObject:rowid1];
[arrImageFromDataBase addObject:personImage];
// NSData *data = [NSData dataWithBytes:sqlite3_column_blob(compiledStatement, 4) length:length];
NSLog(@"%@",personImage);
}
}
}
sqlite3_finalize(compiledStatement);
}
sqlite3_close(database);
NSLog(@"contents of array%@",rowid);
}
这有点令人困惑......抱歉给您带来不便,但确实需要帮助!!
答案 0 :(得分:1)
正如其他人所写,将图像存储在数据库中并不是一个好主意。但这不是问题: - )
我看到你有一个for循环。 当您同时插入多个图像时是否会出现警告? 或者即使您逐个插入图像,它们也会发生?
在第一种情况下,请考虑以下事项:
你在for循环中有UIImagePNGRepresentation
。
此函数返回自动释放的NSData。
仅在当前运行循环结束时清除自动释放池(例如,当程序停止等待用户执行下一个操作时)。
因此,该函数创建的所有NSData都会在运行循环结束时保持活动状态。
因此,如果一次插入10个图像,则要复制内存10 NSData,该NSData将仅在计算结束时被清除。 如果你插入100张图片,同样的故事。
使用仪器 - 分配工具检查是否是这种情况(您将看到NSData占用的内存在循环期间增加,并在计算完成时立即减少)。如果为true,则可以解决创建特定自动释放池的问题。
这样,每个循环都会清除特定的自动释放池
for (jk=0; jk<[globalvalue count];jk++)
{
@autoreleasepool {
NSData *imgData = UIImagePNGRepresentation((UIImage *)[globalvalue objectAtIndex:jk]);
const char *query = "insert into color(img) values (?)";
sqlite3_stmt *searchStatement2;
if (sqlite3_prepare_v2(database,query, -1, &searchStatement2, NULL) == SQLITE_OK)
{
sqlite3_bind_blob(searchStatement2,1, [imgData bytes], [imgData length], NULL);
if (sqlite3_step(searchStatement2) == SQLITE_DONE)
{
NSLog(@"saved");
}
//
// while (sqlite3_step(searchStatement2) == SQLITE_ROW)
// {
// NSString *name2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement2, 0)];
// NSString *category2 = [NSString stringWithUTF8String:(char *)sqlite3_column_text(searchStatement2, 1)];
// NSLog(@"%@ is a %@ color", name, category);
//
//
// }
} sqlite3_finalize(searchStatement2);
}
}
答案 1 :(得分:0)
首先,您必须将图像保存到库中,您可以使用以下代码:
UIImageWriteToSavedPhotosAlbum(UIImage *image, id completionTarget, SEL completionSelector, void *contextInfo);
然后将Library路径保存到sql数据库中。 这将减少db中的大小。您还可以调整图像大小以在图像视图中显示 这样你的内存使用就会减少。
+ (UIImage*)imageWithImage:(UIImage*)image
scaledToSize:(CGSize)newSize;
{
UIGraphicsBeginImageContext( newSize );
[image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)];
UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext();
UIGraphicsEndImageContext();
return newImage;
}
答案 2 :(得分:-1)
如果您将在数据库中保存越来越多的图像,它将给出内存警告,这是非常明显的。因为它创建了一个图像副本并将其保存在数据库中。
只需将图像保存在库中并保存数据库或plist中的路径。