Domanda

Ho impostato un DB SQLite che attualmente legge e scrive perfettamente NSString . Voglio anche salvare un'immagine nel database e richiamarla in seguito. Ho letto un po 'sull'uso di NSData e sulla codifica dell'immagine, ma non sono del tutto sicuro di quale sia la sintassi per ciò che voglio fare. Qualsiasi frammento di codice o esempio sarebbe molto apprezzato.

Il mio processo attuale va così: UIImagePickerController - > L'utente sceglie l'immagine dalle foto - > chosenImage è impostato sull'istanza di UIImageView - > Ora voglio prendere questa immagine e salvarla nel DB

Vorrei menzionare che questa chiamata verrà eventualmente sostituita con una chiamata a un server remoto. Non sono sicuro che questo faccia la differenza per quanto riguarda le prestazioni.

È stato utile?

Soluzione

Un'opzione (e generalmente preferita quando si lavora in SQL) è quella di scrivere l'immagine in un file sul sistema e memorizzare il percorso (o qualche altro tipo di identificatore) nel database.

Altri suggerimenti

Dovrai convertire UIImage ospitato in UIImageView in un BLOB binario per l'archiviazione in SQLite. Per fare ciò, è possibile utilizzare quanto segue:

NSData *dataForImage = UIImagePNGRepresentation(cachedImage);
sqlite3_bind_blob(yourSavingSQLStatement, 2, [dataForImage bytes], [dataForImage length], SQLITE_TRANSIENT);

Questo genererà una rappresentazione PNG della tua immagine, la memorizzerà in un'istanza NSData e quindi assocerà i byte da NSData come BLOB per il secondo argomento nella tua query SQL. Utilizzare UIImageJPEGRepresentation in quanto sopra per archiviare in quel formato, se lo si desidera. Sarà necessario aggiungere una colonna BLOB alla tabella appropriata nel database SQLite.

Per recuperare questa immagine, puoi usare quanto segue:

NSData *dataForCachedImage = [[NSData alloc] initWithBytes:sqlite3_column_blob(yourLoadingSQLStatement, 2) length: sqlite3_column_bytes(yourLoadingSQLStatement, 2)];       
self.cachedImage = [UIImage imageWithData:dataForCachedImage];
[dataForCachedImage release];

La raccomandazione di Apple non è quella di archiviare BLOB in database SQLite di dimensioni superiori a ~ 2 kilobyte.

SQLite organizza i database in pagine. Ogni pagina ha una dimensione di 4 kilobyte. Quando leggi i dati dal file di database SQLite, carica queste pagine in una cache di pagine interna. Sull'iPhone penso che questa cache abbia una dimensione predefinita di 1 megabyte. Questo rende la lettura dei record adiacenti molto veloce perché probabilmente saranno già nella cache della pagina.

Quando SQLite legge il record del database in memoria, legge l'intero record e tutte le pagine che occupa. Quindi, se il tuo record contiene un BLOB, potrebbe occupare molte pagine e dovrai espellere le pagine esistenti dalla cache e sostituirle con le pagine del tuo record BLOB.

Questo non è così male se stai solo scansionando e caricando tutti i tuoi BLOBS per fare qualcosa con loro (visualizzali ad esempio). Ma se dicessi che hai fatto una query in cui volevi solo ottenere alcuni dati che si trovano nella stessa riga del BLOB, questa query sarebbe molto più lenta che se il record non contenesse il BLOB di grandi dimensioni.

Quindi, come minimo, è necessario memorizzare i dati BLOB in una tabella separata. Ad esempio:

CREATE TABLE blobs ( id INTEGER PRIMARY KEY, data BLOB );
CREATE TABLE photos ( id INTEGER PRIMARY KEY, name TEXT, blob_id INTEGER, 
    FOREIGN KEY(blob_id) REFERENCES blobs(id) );

O meglio ancora, archiviare i dati BLOB come file all'esterno del database SQLite.

Nota che potrebbe essere possibile modificare la dimensione della cache della pagina con istruzioni SQL PRAGMA (se non si utilizza CoreData).

Scrittura di immagini su SQLite DB

if(myImage != nil){
    NSData *imgData = UIImagePNGRepresentation(myImage);
    sqlite3_bind_blob(update_stmtement, 6, [imgData bytes], [imgData length], NULL);    
    }
    else {
        sqlite3_bind_blob(update_stmtement, 6, nil, -1, NULL);
    }

Lettura da DB SQLite:

NSData *data = [[NSData alloc] initWithBytes:sqlite3_column_blob(init_statement, 6) length:sqlite3_column_bytes(init_statement, 6)];
        if(data == nil)
            NSLog(@"No image found.");
        else
            self.pictureImage = [UIImage imageWithData:data];   

dovresti prima scrivere l'immagine sul file system. e quindi prendere il percorso dell'immagine e memorizzare quel percorso dell'immagine (URL) come TESTO in sqlite.

La migliore pratica è comprimere l'immagine e memorizzarla nel database o nel file system. Se non ti interessa la risoluzione dell'immagine, puoi andare avanti e persino ridimensionare l'immagine usando:

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

Successivamente puoi usare UIImageJPEGRepresentation per immagini jpeg con un valore di " 0 " per la massima compressione. Oppure puoi usare UIImagePNGRepresentation per immagini png

Autorizzato sotto: CC-BY-SA insieme a attribuzione
Non affiliato a StackOverflow
scroll top