Je suis nouveau sur iOS. J'ai essayé de faire une application qui stockera une image capturée à partir de la caméra dans CoreData
. Je sais maintenant comment stocker des données telles que NSString
s, NSDate
et d'autres types, mais ayant du mal à stocker une image. J'ai lu tellement d'articles disant que vous devez l'écrire sur le disque et écrire dans un fichier, mais je n'arrive pas à le comprendre.
Le code suivant est celui que j’ai utilisé pour stocker d’autres données dans des données de base.
- (IBAction)submitReportButton:(id)sender
{
UrbanRangerAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"PotholesDB" inManagedObjectContext:appDelegate.managedObjectContext];
NSManagedObject *newPothole = [[NSManagedObject alloc]initWithEntity:entity insertIntoManagedObjectContext:managedObjectContext];
[newPothole setValue:self.relevantBody.text forKey:@"relevantBody"];
[newPothole setValue:self.subjectReport.text forKey:@"subjectReport"];
[newPothole setValue:self.detailReport.text forKey:@"detailReport"];
// [newPothole setValue:self.imageView forKey:@"photo"];
NSDate *now = [NSDate date];
//NSLog(@"now : %@", now);
NSString *strDate = [[NSString alloc] initWithFormat:@"%@", now];
NSArray *arr = [strDate componentsSeparatedByString:@" "];
NSString *str;
str = [arr objectAtIndex:0];
NSLog(@"now : %@", str);
[newPothole setValue:now forKey:@"photoDate"];
[newPothole setValue:self.latitudeLabel.text forKey:@"latitude"];
[newPothole setValue:self.longitudeLabel.text forKey:@"longitude"];
[newPothole setValue:self.addressLabel.text forKey:@"streetName"];
[newPothole setValue:streeNameLocation forKey:@"location"];
NSError *error;
[managedObjectContext save:&error];
UIAlertView *ll = [[UIAlertView alloc] initWithTitle:@"Saving" message:@"Saved data" delegate:nil cancelButtonTitle:@"OK" otherButtonTitles:nil];
[ll show];
}
Vous pouvez stocker des images dans Core Data en utilisant le type d'attribut Données binaires. Cependant, vous devez être conscient de certaines choses:
Toujours convertir votre UIImage en un format de données portable comme png ou jpg Par exemple:
NSData *imageData = UIImagePNGRepresentation(image);
Activer "Autorise le stockage externe" sur cet attribut Core Data déplacera les données vers un fichier externe si elles atteignent un certain seuil. Ce fichier est également entièrement géré par Core Data, vous n’avez donc pas à vous en préoccuper.
Si vous rencontrez des problèmes de performances, essayez de déplacer l'attribut Données binaires vers une entité distincte.
Vous devez résumer la conversion en NSData derrière l'interface de votre sous-classe NSManagedObject afin de ne pas avoir à vous soucier des conversions de UIImage vers NSData ou inversement.
Si vos images ne sont pas étroitement liées aux entités de votre modèle, nous vous suggérons de les stocker en dehors de Core Data.
Dans la sous-classe xcdatamodelId, déclarez l'entité d'image en tant que NSData
... vous ne pouvez pas utiliser le format UIImage
, car les données d'image sont au format binaire.
@property (nonatomic, retain) NSData *imag;
Dans le fichier d'implémentation .. convertir UIImage
en NSData
UIImage *sampleimage = [UIImage imageNamed:@"sampleImage.jpg"];
NSData *dataImage = UIImageJPEGRepresentation(sampleimage, 0.0);
Puis finalement le sauvegarder
[obj setValue:dataImage forKey:@"imageEntity"]; // obj refers to NSManagedObject
- (void)imageChanged:(UIImage*)image{
if (self.detailItem) {
[self.detailItem setValue:UIImagePNGRepresentation(image) forKey:kSignatureImage];
}
}
En cela, un très bref exemple. self
est un contrôleur de vue utilisant des données de base et self.detailItem est le NSManagedObject habituel. Dans ce projet, je n'ai pas créé de classes de modèle pour les entités, mais j'utilise strictement le modèle KVC pour accéder aux attributs. Comme vous pouvez le deviner, l’attribut est nommé "signatureImage"
que j'avais défini dans une constante #define kSignatureImage
.
C’est là que l’image est restaurée à partir des données principales:
self.signatureCanvas.image = [UIImage imageWithData:[self.detailItem valueForKey:kSignatureImage]];
Encore une fois, self
est un contrôleur de vue, signatureCanvas
est une sous-classe UIImageView
et .image
est sa propriété normale image
héritée de UIImageView
. detailItem
, encore une fois, est l'habituel NSManagedObject
.
L'exemple est tiré d'un projet sur lequel je travaille actuellement.
Il existe des avantages et des inconvénients pour stocker des objets de données volumineux tels que des images dans des données de base ou les séparer dans des fichiers. Les stocker dans des fichiers signifie qu'il vous incombe de les supprimer lorsque les objets de données associés sont supprimés. Cela génère une surcharge de codage et peut être volatile pour les erreurs de programmation. D'autre part, cela peut ralentir la base de données sous-jacente. Je n'ai pas encore assez d'expérience avec cette approche que je pourrais partager en matière de performance. Au final, l’espace disque occupé est à peu près de la même taille.
Pour Swift 5 et Swift 4.2
convertir UIImage
en Data
:
let imageData = image.jpegData(compressionQuality: 1.0)
enregistrer dans CoreData
:
let object = MyEntity(context: managedContext) //create object of type MyEntity
object.image = imageData //add image to object
do {
try managedContext.save() //save object to CoreData
} catch let error as NSError {
print("\(error), \(error.userInfo)")
}
Il est possible de stocker des images dans Core Data en tant que UIImage. Bien que cela ne soit pas considéré comme une bonne pratique, les bases de données ne sont pas conçues pour stocker des fichiers. Nous n'utilisons pas les données de base pour stocker les images directement. Nous utilisons plutôt le chemin d'accès au fichier où les données d'image sont stockées sur votre téléphone.
Quoi qu'il en soit, la meilleure méthode que j'ai découverte lors de l'élaboration d'un projet parallèle est illustrée ci-dessous.
Sélectionnez l'attribut de type Image que vous voulez et choisissez transformable comme type
Allez dans l'éditeur et sélectionnez Create NSManagedObject Subclass
Le processus créera 2 fichiers Swift en fonction du nombre de vos entités (je n'avais qu'une seule entité). Maintenant, sélectionnez le fichier <EntityName> + CoreDataProperties.Swift
Et importer UIKit
Si, en cliquant Aller à la définition pour le @NSManaged public var UIImage definition
, Votre travail est terminé.
Effectuez des actions sur les entités exactement comme vous le feriez et vous pourrez extraire, enregistrer, modifier l’attribut d’image en déclassant <EntityName>?.value(forKey: "<attributeName>") as? UIImage
.
Je devais utiliser l'entité sous la forme NSManagedObject
et, pour une raison quelconque, je ne pouvais pas accéder à l'image directement à partir de la sous-classe créée.
Peu de liens qui pourraient vous aider à passer à travers cette
https://stackoverflow.com/a/3909082/5580
Je ne sais pas pourquoi vous souhaitez stocker une image dans des données de base, alors qu'un autre stockage persistant est disponible dans iOS. Si vous souhaitez simplement stocker une image à des fins de cache, vous pouvez la stocker dans un répertoire de documents ou dans un répertoire de cache. Bonne codage ...
Veuillez vous reporter ci-dessous à l'URL, Comment stocker et récupérer des images dans le répertoire du document.
http://www.wmdeveloper.com/2010/09/save-and-load-uiimage-in-documents.html