2016-04-22 12 views
0

Ich versuche, eine BLOB-Daten von SignatureView mit diesem Code einfügen, aber wenn ich tatsächlich die Datenbank durchsuchen gibt es null anstelle von Daten. Mein Signaturtabellenschema ist unten angegeben.iOS SQLite Blob Daten speichern NULL

Create Tabellenzeichen (id Integer Primärschlüssel AUTOINCREMENT, Bildblob, functionid integer);

-(void)storeImageData:(NSData *)imageData withInvoiceID:(NSInteger)invoiceID{ 

    NSString *dbPath = [[[NSBundle mainBundle] resourcePath ]stringByAppendingPathComponent:@"database.sqlite3"]; 
    const char *dbpath = [dbPath UTF8String]; 
    sqlite3 *contactDB; 

    sqlite3_stmt *statement; 

    NSLog(@"%@",dbPath); 
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     int invoiceIDINT = (int)invoiceID; 
    // 
     NSString *insertSQL = [NSString stringWithFormat: @"INSERT INTO sign (image,invoiceid) VALUES (?,%d)", invoiceIDINT]; 

     const char *insert_stmt = [insertSQL UTF8String]; 

     sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL); 
     if (sqlite3_step(statement) == SQLITE_DONE) 
     { 
      sqlite3_bind_blob(statement, 2, [imageData bytes], [imageData length], SQLITE_TRANSIENT); 
      sqlite3_step(statement); 

     } else { 
      const char *Error = sqlite3_errmsg(database); 
      NSString *error = [[NSString alloc]initWithUTF8String:Error]; 
      UIAlertView *view = [[UIAlertView alloc]initWithTitle:@"Error2" message:[NSString stringWithFormat:@"Last inserted ID: %@",error] delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; 
      [view show]; 
     } 
     sqlite3_finalize(statement); 
     sqlite3_close(contactDB); 
    } 


} 

Antwort

2
  1. immer das Ergebnis sqlite3_prepare_v2 überprüfen. Wenn dies fehlschlägt, protokollieren Sie das Problem mit sqlite3_errmsg.
  2. Nur sqlite3_finalize anrufen, wenn sqlite3_prepare_v2 erfolgreich ist.
  3. Sie erhalten NULL für den Blob, weil Ihr Aufruf an den falschen Spaltenindex übergibt. Es sollte 1, nicht 2 sein, da Sie an die erste ? in Ihrer INSERT Anweisung binden möchten.
  4. Warum die Inkonsistenz? Warum verwenden Sie stringWithFormat, um den Wert für die invoiceid Spalte festzulegen und dann sqlite_bind_xxx für die image Spalte zu verwenden? Sie sollten beide binden. Verwenden Sie niemals stringWithFormat, um eine Abfrage zu erstellen.
  5. Sie rufen sqlite3_step zweimal. Rufen Sie es nur einmal an und binden Sie Ihre Werte, bevor Sie sie aufrufen.
  6. Sie scheinen in eine Datenbank im Ressourcenpaket Ihrer App zu schreiben. Sie können das nicht auf einem echten Gerät tun. Es funktioniert im Simulator, aber nicht auf echten iOS-Geräten. Sie müssen Ihre Datenbankdatei in den Ordner Dokumente stellen.

all oben gegeben, den Code in etwa so sein sollte:

-(void)storeImageData:(NSData *)imageData withInvoiceID:(NSInteger)invoiceID{ 
    // This is wrong - you need to update this to use the Documents folder 
    NSString *dbPath = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:@"database.sqlite3"]; 
    const char *dbpath = [dbPath UTF8String]; 
    NSLog(@"%@",dbPath); 

    sqlite3 *contactDB; 
    if (sqlite3_open(dbpath, &contactDB) == SQLITE_OK) 
    { 
     const char *insert_stmt = "INSERT INTO sign (image, invoiceid) VALUES (?, ?)"; 

     sqlite3_stmt *statement; 
     if (sqlite3_prepare_v2(contactDB, insert_stmt, -1, &statement, NULL) == SQLITE_OK) { 
      sqlite3_bind_blob(statement, 1, [imageData bytes], [imageData length], SQLITE_TRANSIENT); 
      sqlite3_bind_int(statement, 2, (int)invoiceID); 

      if (sqlite3_step(statement) == SQLITE_DONE) { 
       // Row inserted successfully 
      } else { 
       const char *Error = sqlite3_errmsg(contactDB); 
       NSString *error = [[NSString alloc] initWithUTF8String:Error]; 
       UIAlertView *view = [[UIAlertView alloc] initWithTitle:@"Error2" message:[NSString stringWithFormat:@"Last inserted ID: %@",error] delegate:nil cancelButtonTitle:@"Cancel" otherButtonTitles:nil, nil]; 
       [view show]; 
      } 

      sqlite3_finalize(statement); 
     } else { 
      NSLog(@"Unable to prepare statement %s: %s", insert_stmt, sqlite3_errmsg(contactDB)); 
     } 

     sqlite3_close(contactDB); 
    } else { 
     NSLog(@"Unable to open database at path %@: %s", dbPath, sqlite3_errmsg(contactDB)); 
    } 
} 
+0

'sqlite3_finalize()' darf auf einer NULL-Anweisung aufgerufen werden. –

+1

@ CL. Aber warum? Sie müssen nur eine geöffnete Datenbank schließen. Sie müssen nur eine vorbereitete Aussage abschließen. – rmaddy

+0

Es kann Situationen geben, in denen das bedingungslose Aufrufen von 'sqlite3_finalize' einfacher ist. –