ios 如何在核心数据中存储图像

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/16685812/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-30 23:40:43  来源:igfitidea点击:

How to store an image in core data

iosobjective-ccore-data

提问by Sipho Koza

I'm new to iOS. I've been trying to make an application that will store an image captured from the camera into CoreData. I now know how to store data like NSStrings, NSDateand other type but struggling to store an image. I've read so many articles saying you must write it to the disk and write to a file, but I can't seem to understand it.

我是 iOS 新手。我一直在尝试制作一个应用程序,它将从相机捕获的图像存储到CoreData. 我现在知道如何存储像NSStringsNSDate和其他类型的数据,但很难存储图像。我读了很多文章说必须将其写入磁盘并写入文件,但我似乎无法理解。

The following code is the one i used to store other data to core data.

以下代码是我用来将其他数据存储到核心数据的代码。

- (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];
} 

回答by jansenmaarten

You can store images in Core Data using the Binary Data attribute type. However you should be aware of a few things:

您可以使用二进制数据属性类型将图像存储在 Core Data 中。但是,您应该注意以下几点:

  • Always convert your UIImage to a portable data format like png or jpg For example:

    NSData *imageData = UIImagePNGRepresentation(image);

  • Enable "Allows external storage" on this attribute descriptionCore Data will move the data to an external file if it hits a certain threshold. This file is also completely managed by Core Data, so you don't have to worry about it.

  • If you run into performance issues, try moving the Binary Data attribute to a separate entity.

  • You should abstract the conversion to NSData behind the interface of your NSManagedObject subclass, so you don't have to worry about conversions from UIImage to NSData or vice versa.

  • If your images are not strongly related to the entities in your model, I would suggest storing them outside of Core Data.

  • 始终将您的 UIImage 转换为可移植的数据格式,例如 png 或 jpg 例如:

    NSData *imageData = UIImagePNGRepresentation(image);

  • 在此属性上启用“允许外部存储”, 描述如果达到某个阈值,Core Data 会将数据移动到外部文件。这个文件也完全由 Core Data 管理,所以你不必担心。

  • 如果遇到性能问题,请尝试将 Binary Data 属性移至单独的实体。

  • 您应该在 NSManagedObject 子类的接口后面抽象到 NSData 的转换,因此您不必担心从 UIImage 到 NSData 的转换,反之亦然。

  • 如果您的图像与模型中的实体没有密切关系,我建议将它们存储在 Core Data 之外。

回答by Jemythehigh

In xcdatamodelId subclass declare image entity as NSData... you can't use UIImageformat because image data is in binary format.

在 xcdatamodelId 子类中,将图像实体声明为NSData...您不能使用UIImage格式,因为图像数据是二进制格式。

@property (nonatomic, retain) NSData *imag;

In Implementation file.. convert UIImageto NSData

在实现文件..转换UIImageNSData

UIImage *sampleimage = [UIImage imageNamed:@"sampleImage.jpg"];

NSData *dataImage = UIImageJPEGRepresentation(sampleimage, 0.0);

Then finally save it

然后最后保存

[obj setValue:dataImage forKey:@"imageEntity"]; // obj refers to NSManagedObject

回答by nomnom

For Swift 5and Swift 4.2

对于Swift 5Swift 4.2

  1. convert UIImageto Data:

    let imageData = image.jpegData(compressionQuality: 1.0)
    
  2. save to 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)")
    }
    
  1. 转换UIImageData

    let imageData = image.jpegData(compressionQuality: 1.0)
    
  2. 保存到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)")
    }
    

回答by Hermann Klecker

- (void)imageChanged:(UIImage*)image{

    if (self.detailItem) {
        [self.detailItem setValue:UIImagePNGRepresentation(image) forKey:kSignatureImage];
    }
}

In this a very brief example. selfis a view controller using core data and self.detailItem is the usual NSManagedObject. In that project I did not create model classes for the entities but strictly use the KVC pattern to access the attributes. As you might guess, the attribute is named "signatureImage"which I had defined in an #define constant kSignatureImage.

这是一个非常简短的例子。self是一个使用核心数据的视图控制器,self.detailItem 是通常的 NSManagedObject。在那个项目中,我没有为实体创建模型类,而是严格使用 KVC 模式来访问属性。正如您可能猜到的,该属性的名称"signatureImage"是我在 #define 常量中定义的kSignatureImage

This is where the image is restored from core data:

这是从核心数据恢复图像的地方:

self.signatureCanvas.image =  [UIImage imageWithData:[self.detailItem valueForKey:kSignatureImage]];

Again, selfis a view controller, signatureCanvasis a UIImageViewsubclass and .imageis its regular imageproperty inherited from UIImageView. detailItem, again, is the usual NSManagedObject.

同样,self是一个视图控制器,signatureCanvas是一个UIImageView子类,并且.imageimageUIImageView. detailItem,再次,是通常的NSManagedObject

The example is taken from a project I am currently working on.

该示例取自我目前正在进行的一个项目。

There are pros and cons for storing large data objects like images in core data or having them separated in files. Storing them in files means that you are responsible for deleting them when the related data objects are deleted. That provides coding overhead and may be volatile for programming errors. On the other hand, it may slow down the underlying database. I have not yet enough experience with this approach that I could share with respect to performance. In the end, the disk storage occupied is about the same size in total.

在核心数据中存储像图像这样的大型数据对象或将它们分开在文件中有利有弊。将它们存储在文件中意味着您有责任在删除相关数据对象时删除它们。这提供了编码开销并且对于编程错误可能是易失性的。另一方面,它可能会减慢底层数据库的速度。我对这种方法还没有足够的经验,我可以在性能方面分享。最终,占用的磁盘存储总量大致相同。

回答by Utkarsh Jaiswal

It is possible to store images in Core Data as UIImage. Although this is not considered to be good practice as Databases are not meant for storing files. We don't use core data to store the images directly instead we use the file path to where the image data is stored on your phone.

可以将图像作为 UIImage 存储在 Core Data 中。尽管这不被认为是一种好的做法,因为数据库并不用于存储文件。我们不使用核心数据直接存储图像,而是使用文件路径到手机上存储图像数据的位置。

Anyways, the best method I found out while developing a side-project is demonstrated below

无论如何,我在开发副项目时发现的最佳方法如下所示

  1. Set the entity codeGen to Manual/None

  2. Select the attribute you want to be of Image type and choose transformableas it's type

  3. Enter Custom class identifier as UIImage

  4. Go to editor and select Create NSManagedObject Subclass

  5. The Process will create 2 swift files depending on the number of your entities(I only had 1 entity). Now, select the <EntityName> + CoreDataProperties.swiftfile and import UIKit

  1. 将实体 codeGen 设置为 Manual/None

  2. 选择您想要的图像类型的属性并选择可变形作为它的类型

  3. 输入自定义类标识符作为 UIImage

  4. 转到编辑器并选择创建 NSManagedObject 子类

  5. 该流程将根据您的实体数量创建 2 个 swift 文件(我只有 1 个实体)。现在,选择<EntityName> + CoreDataProperties.swift文件并导入 UIKit

If, on clicking Jump to Definitionfor the @NSManaged public var UIImage definitionyour work is done.

如果单击“跳转到定义”以查看 @NSManaged 公共变量,UIImage definition您的工作就完成了。

Perform actions on the entities just like you would and you will be able to fetch, save, edit the image attribute by down-casting <EntityName>?.value(forKey: "<attributeName>") as? UIImage.

像您一样对实体执行操作,您将能够通过向下转换来获取、保存和编辑图像属性<EntityName>?.value(forKey: "<attributeName>") as? UIImage

I had to use the entity as NSManagedObjecttype and was for some reason not able to access the image directly from the created subclass.

我不得不使用实体作为NSManagedObject类型,并且由于某种原因无法直接从创建的子类访问图像。

回答by Mangesh

I don't know why you want to store image in core data, while there is other persistent storage available in iOS. If you just want to store image for cache purpose, you can store it in document directory or cache directory. Happy Coding...

我不知道您为什么要将图像存储在核心数据中,而 iOS 中还有其他持久存储可用。如果您只想存储图像用于缓存目的,您可以将其存储在文档目录或缓存目录中。快乐编码...

Please refer below URL, How to store and retrieve images in document directory.

请参考以下 URL,如何在文档目录中存储和检索图像。

http://www.wmdeveloper.com/2010/09/save-and-load-uiimage-in-documents.html

http://www.wmdeveloper.com/2010/09/save-and-load-uiimage-in-documents.html

Saving image to Documents directory and retrieving for email attachment

将图像保存到 Documents 目录并检索电子邮件附件

How do I create a temporary file with Cocoa?

如何使用 Cocoa 创建临时文件?