2010-10-11 14 views
31

Sto sviluppando un'applicazione che richiede circa 100 immagini o forse più da pre-inserire nel database dei Core Data insieme ad altre informazioni correlate.Come posso archiviare UIImages nel mio database di Core Data?

Ora posso aggiungere facilmente altri dati semplicemente scrivendo poche righe di codice ma per UIImages non sono sicuro di come farlo senza scrivere molto codice. Mi chiedevo: c'è comunque modo di farlo facilmente, o se non c'è qual è il modo migliore per ottenere questo con il minimo sforzo.

Inoltre, è possibile archiviare le immagini in un database Core Data o dovremmo solo salvare gli indirizzi delle immagini sul file system locale?

risposta

55

Memorizzare le immagini in un database Core Data è piuttosto semplice. Devi solo contrassegnare l'attributo dell'immagine come trasformabile e creare una sottoclasse di NSValueTransformer. All'interno di questa sottoclasse, aggiungere il codice come il seguente:

+ (Class)transformedValueClass 
{ 
    return [NSData class]; 
} 

+ (BOOL)allowsReverseTransformation 
{ 
    return YES; 
} 

- (id)transformedValue:(id)value 
{ 
    if (value == nil) 
     return nil; 

    // I pass in raw data when generating the image, save that directly to the database 
    if ([value isKindOfClass:[NSData class]]) 
     return value; 

    return UIImagePNGRepresentation((UIImage *)value); 
} 

- (id)reverseTransformedValue:(id)value 
{ 
    return [UIImage imageWithData:(NSData *)value]; 
} 

Per l'attributo trasformabile, specificare il nome di questa sottoclasse come il valore Transformer nome.

È possibile quindi creare una sottoclasse NSManagedObject per l'entità che ospita questo attributo immagine e dichiarare una proprietà per questo attributo immagine:

@property(nonatomic, retain) UIImage *thumbnailImage; 

si può leggere UIImages e scrivere UIImages a questa proprietà e saranno trasparente cambiato da e verso NSData per essere memorizzato nel database.

La scelta di farlo dipende dal caso specifico. Le immagini più grandi probabilmente non dovrebbero essere archiviate in questo modo, o almeno dovrebbero essere nella loro stessa entità in modo che non vengano recuperate in memoria finché non viene seguita una relazione con loro. Le miniature di piccole dimensioni sono probabilmente perfette per inserire il database in questo modo.

+51

Solo un follow-up per chiunque lo verifichi ora: UIImage ora è conforme a NSCoding in iOS 5. Se sei in grado di scegliere come target iOS 5 e versioni successive, puoi semplicemente impostare l'attributo e Trasformabile ed essere fatto. È anche possibile selezionare "Permette l'archiviazione esterna" per far sì che le immagini più grandi vengano salvate automaticamente al di fuori del proprio archivio di Core Data automaticamente. – atticus

+0

Il codice che viene generato automaticamente da CoreData ha ID anziché UIImiage * come attributo. È normale? Dovremmo cambiarlo? –

+1

@JimThio - Giusto, questo è l'impostazione predefinita. Perché so che imposterò una UIImage su questa proprietà trasformata, cambio il tipo in UIImage. Ciò aiuta a mantenere il mio codice chiaro e fornisce un controllo di integrità se cerco di utilizzare questa proprietà nel modo sbagliato. –

8

Apple fa fornire qualche consiglio intorno BLOB: Large Data Objects (BLOBs)

Se l'applicazione utilizza grandi BLOB ("oggetti grandi binari", come immagine e dati audio), è necessario fare attenzione per ridurre al minimo spese generali. La definizione esatta di di "piccola", "modesta" e "grande" è fluida e dipende dall'utilizzo di un'applicazione . Una regola allentata di thumb è che gli oggetti nell'ordine di dimensioni di kilobyte sono di dimensioni "modeste" e quelli nell'ordine di dimensioni di megabyte sono di dimensioni "grandi". Alcuni sviluppatori hanno ottenuto una buona prestazione con BLOB 10 MB in un database . D'altra parte, se un'applicazione ha milioni di righe in una tabella , anche 128 byte potrebbero essere un CLOB di dimensioni "modeste" (carattere grande ) che deve essere normalizzato in una tabella separata.

In generale, se è necessario archiviare BLOB in un archivio persistente, è necessario utilizzare un archivio SQLite.L'XML e binari negozi richiedono che l'intero oggetto grafico risiedono in memoria, e memorizzare scrive sono atomiche (vedi “persistenti deposito Caratteristiche”), il che significa che non si affrontare in modo efficace con le grandi oggetti di dati. SQLite può scalare fino a gestire database di dimensioni estremamente grandi. correttamente utilizzata, SQLite fornisce buone prestazioni per database fino a 100 GB, e una singola riga può contenere fino a 1 GB (anche se naturalmente lettura 1 GB di dati in memoria è un costoso un'operazione non importa quanto sia efficiente il repository ) .

Un BLOB rappresenta spesso un attributo di un esempio entità-per, una fotografia potrebbe essere un attributo di un dipendente entità. Per i BLOB (e CLOB) di dimensioni da piccole a modeste (e CLOB), è necessario creare un'entità separata per i dati e creare una relazione uno a uno in posizione dell'attributo. Ad esempio, è possibile creare dipendenti e fotografare entità con una relazione uno-a-uno tra di loro, in cui il rapporto da dipendente a fotografia sostituisce attributo la fotografia del dipendente. Questo modello ottimizza i vantaggi dell'oggetto con errori (vedere "Errore e Uniquing"). Qualsiasi fotografia data è recuperata solo se è effettivamente necessaria (se la relazione è attraversata).

E 'meglio, tuttavia, se si è in grado di memorizzare BLOB come risorse sul filesystem, e per mantenere i collegamenti (come ad esempio gli URL o percorsi) a quelle risorse. È quindi possibile caricare un BLOB come e, se necessario.

11

Un buon esempio del trasformatore di immagine come descritto sopra è nell'applicazione demo iPhoneCoreDataRecipes.

+0

Eccellente! Grazie per il testa a testa! – Fogmeister

+1

Ecco il collegamento corrente all'esempio: https://developer.apple.com/library/content/SampleCode/iPhoneCoreDataRecipes/Introduzione/intro.html –

Problemi correlati