2013-07-05 54 views
0

我正在圖像保存在數據庫中,也使用AV捕獲會話來創建自定義相機。但隨着我在數據庫中保存越來越多的圖像,它會給出內存警告。內存問題在ios

當我停止保存圖像數據庫的應用程序很好,爲什麼會發生?這是否由於數據庫大小的增加而發生?

當前代碼:

-(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

你用ARC嗎?清理你的英語。 – Raptor

+0

是我使用弧。 – mandeep

+5

在數據庫中存儲的圖像是不恰當的做法。 –

回答

-1

它是非常明顯的,如果你將在數據庫中保存越來越多的圖像它會給內存警告。因爲它創建圖像的副本並將其保存在數據庫中。

只需將圖像保存到庫中,並在數據庫或plist中保存路徑即可。

+0

這不是「非常明顯」。即使將圖像存儲在數據庫中不是一個好主意,這也不會導致OP描​​述的問題。您可以將「越來越多」的圖像保存到數據庫中,如果您知道內存管理規則的基礎知識,則不會出現問題和內存警告。 – LombaX

+0

是的,使用ARC它不是一個很好的理由忘記內存管理規則:-)他們仍然重要 – LombaX

1

正如其他人所寫,將圖像存儲在數據庫中並不是一個好主意。但這不是問題:-)

我看到你有一個for循環。 當您同時插入多個圖像時是否發生警告? 或者即使插入圖像「一個一個」,它們也會發生?

在第一種情況下,可以這樣考慮:

你有UIImagePNGRepresentation裏面的for循環。 該函數返回一個自動釋放的NSData。 自動釋放池僅在當前運行循環結束時清除(例如,程序停止等待用戶執行下一個操作時)。因此,由該函數創建的所有NSData在運行循環結束時保持活動狀態。

因爲這個原因,如果一次插入10張圖像,你在內存中複製10個NSData,只有在計算結束時纔會被清除。 如果插入100張圖片,則是同一個故事。

使用的儀器 - 分配工具來檢查,如果是這樣的話(你會看到NSData的內存佔用的循環過程中增加,並立即當運算完成後減少)。如果屬實,您可以解決創建特定的自動釋放池。

與此,具體的自動釋放池在每個循環

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); 
    } 

} 
0

首先清除你必須將圖像保存到您可以使用下面的代碼庫:

UIImageWriteToSavedPhotosAlbum(UIImage *image, id completionTarget, SEL completionSelector, void *contextInfo);

然後將庫路徑保存到你的sql數據庫中。 這將減少數據庫中的大小。您也可以調整圖像大小以顯示在圖像視圖 中,以便減少內存使用量。

+ (UIImage*)imageWithImage:(UIImage*)image 
      scaledToSize:(CGSize)newSize; 
{ 
    UIGraphicsBeginImageContext(newSize); 
    [image drawInRect:CGRectMake(0,0,newSize.width,newSize.height)]; 
    UIImage* newImage = UIGraphicsGetImageFromCurrentImageContext(); 
    UIGraphicsEndImageContext(); 

    return newImage; 
}