19.03.2011
Einleitung
Ausgehend von dem Tutorial Simple Core Data Command Line Importer (Xcode 3.2) wird im Datenmodell nun ein zusätzliches Attribut vom Typ Binary Data (NSData
) hinzugefügt, um Binärdaten (BLOBs) zu speichern und zu lesen. In dem Beispiel werden Bilder (jpgs) verwendet. Allerdings können auf die gleiche Weise alle anderen Dateitypen gespeichert und gelesen werden. Beispielsweise PDF-Datein, Video-Dateien oder Musik-Dateien wie MP3s.
Datenmodell erweitern
Als erstes wird der Entity Person
ein Attribut personimage
vom Typ Binary Data (NSData
) hinzugefügt. Dazu selektiert man die Entity Person
und klickt auf das kleine Pluszeichen. In dem Menü wählt man dann Add Attribute aus:
Das neue Attribut bekommt den Namen personimage
, den Typ Binary Data (NSData
) und ist optional
. Danach sollte das Code Data Datenmodell folgendermaßen aussehen:
In dem Tutorial Simple Core Data Command Line Importer (Xcode 3.2) wurde eine Textdatei Personen.txt
für den Import verwendet. Diese wird um Dateipfade zu Bildern ergänzt:
Jörn Hameister ~/Pictures/HameisterJ.jpg
Donald Duck ~/Pictures/DuckD.jpg
Bart Simpson ~/Pictures/SimpsonB.jpg
Binärdaten (BLOBs) speichern
Im Folgenden wird beschrieben wie eine jpg-Datei von der Festplatte gelesen wird und anschließend als NSData
-Objekt mit Core Data persistiert wird.
In der Datei SimpleCommandLineImporter.m
muß die Methode NSData* loadImage(NSString* path)
ergänzt werden.
NSData* loadImage(NSString* path) {
NSString *imagePath = [path stringByResolvingSymlinksInPath];
NSFileManager *fileManager = [NSFileManager defaultManager];
BOOL fileExists = [fileManager fileExistsAtPath:imagePath];
if(fileExists) {
return [[NSData alloc] initWithContentsOfFile:imagePath];
}
return nil;
}
Als erstes wird der Pfad path
in einen absoluten Pfad umgewandelt (mehr dazu unter Dateipfade). Danach wird der NSFileManager
verwendet, um zu überprüfen, ob die Datei vorhanden ist. Wenn die Datei existiert, dann wird sie in ein Object vom Typ NSData
eingelesen und zurückgegeben.
Anschließend werden in der for
-Schleife der main
-Methode die zwei Zeilen unterhalb von // Add the image
ergänzt:
for(id person in persons) {
NSArray *firstnameLastname = [person componentsSeparatedByString:@" "];
// Add a new Person
NSManagedObject *personMO =
[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:context];
[personMO setValue:[firstnameLastname objectAtIndex:0] forKey:@"personfirstname"];
[personMO setValue:[firstnameLastname objectAtIndex:1] forKey:@"personname"];
// Add the image
NSData * imageData = loadImage([firstnameLastname objectAtIndex:2]);
[personMO setValue:imageData forKey:@"personimage"];
}
Die erste Zeile ruft die neue Methode zum Laden der Datei auf. Die zweite Zeile sorgt dafür, daß der Dateiinhalt in dem Attribut personimage
gespeichert wird.
Binärdaten (BLOBs) auslesen
Hier wird erklärt, wie ein NSData
-Objekt mit einem NSFetchRequest
aus Core Data ausgelesen werden kann. Nach dem Auslesen, werden die Daten auf die Festplatte geschrieben. In dem Beispiel wird davon ausgegangen, daß es sich um die jpg-Datei handelt, die oben persistiert wurde.
In der Datei SimpleCommandLineImporter.m
muß die Methode fetchImageAndSaveToDisk(NSString* toPath)
ergänzt werden.
void fetchImageAndSaveToDisk(NSString *toPath) {
NSManagedObjectContext *context = managedObjectContext();
NSFetchRequest *request = [[NSFetchRequest alloc] init];
[request setEntity:[NSEntityDescription entityForName:@"Person" inManagedObjectContext:context]];
NSError *error = nil;
NSArray *persons = [context executeFetchRequest:request error:&error];
if(error) {
NSLog(@"Cannot execute NSFetchRequest: %@", [error localizedDescription]);
return ;
}
NSString *imagePath = [toPath stringByResolvingSymlinksInPath];
for(NSManagedObject *person in persons) {
NSData * imageData = [person valueForKey:@"personimage"];
[imageData writeToFile:
[imagePath stringByAppendingPathComponent:[[NSString alloc]
initWithFormat:@"%@%c.jpg",
[person valueForKey:@"personname"],
[[person valueForKey:@"personfirstname"] characterAtIndex:0]]]
atomically:TRUE];
}
}
Der obere Teil der Methode (bis Zeile 12) ist identisch mit dem NSFetchRequest
aus dem Beispiel Auslesen von Core Data-Daten mit NSFetchRequest. In der for
-Schleife in Zeile 15 wird über alle Personen iteriert. Von jeder Person werden die Bilddaten ausgelesen und in einem Objekt von Typ NSData
abgelegt. Diese Klasse hat eine Methode writeToFile:atomically
, die benutzt wird um die Bilddaten auf die Festplatte zu schreiben. Der erste Parameter dieser Methode ist der Dateiname inklusive Pfad. Der Pfad ist in der Variable imagePath
gespeichert. Der Dateiname wird aus Nachnamen (personname
), dem ersten Buchstaben des Vornamens (personfirstname
) und der Dateiendung (.jpg
) zusammengesetzt.
In dem Beispiel wird nicht überprüft, ob schon eine Datei gleichen Namens vorhanden ist.
Um die Bilder auszulesen und auf Festplatte zu schreiben, muß nun die Methode fetchImageAndSaveToDisk(NSString *toPath)
in der main
-Methode aufgerufen werden.
fetchImageAndSaveToDisk(@"~/Documents/tmp/");
Es ist darauf zu achten, daß das Verzeichnis ~/Documents/tmp/
auf der Festplatte existiert.