簡體   English   中英

如何在核心數據中存儲圖像

[英]How to store an image in core data

我是iOS新手。 我一直在嘗試制作一個應用程序,它將將從相機捕獲的圖像存儲到CoreData 我現在知道如何存儲數據,例如NSStringNSDate和其他類型,但是卻很難存儲圖像。 我讀過很多文章,說您必須將其寫入磁盤並寫入文件,但是我似乎無法理解。

以下代碼是我用來將其他數據存儲到核心數據的代碼。

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

您可以使用Binary Data屬性類型將圖像存儲在Core Data中。 但是,您應該注意以下幾點:

  • 始終將UIImage轉換為可移植的數據格式,例如png或jpg例如:

    NSData *imageData = UIImagePNGRepresentation(image);

  • 在此屬性上啟用“允許外部存儲” 描述 如果核心數據達到某個閾值,它將把數據移動到一個外部文件中。 該文件也由Core Data完全管理,因此您不必擔心。

  • 如果遇到性能問題,請嘗試將“二進制數據”屬性移動到單獨的實體。

  • 您應該在NSManagedObject子類的接口之后抽象到NSData的轉換,因此您不必擔心從UIImage到NSData的轉換,反之亦然。

  • 如果您的圖像與模型中的實體關系不大,建議將其存儲在Core Data之外。

在xcdatamodelId子類中,將圖像實體聲明為NSData ……您不能使用UIImage格式,因為圖像數據是二進制格式。

@property (nonatomic, retain) NSData *imag;

在實現文件中。將UIImage轉換為NSData

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

NSData *dataImage = UIImageJPEGRepresentation(sampleimage, 0.0);

然后最后保存

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

對於Swift 5Swift 4.2

  1. UIImage轉換為Data

     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)") } 
- (void)imageChanged:(UIImage*)image{

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

在這個非常簡單的例子中。 self是使用核心數據的視圖控制器,self.detailItem是通常的NSManagedObject。 在那個項目中,我沒有為實體創建模型類,而是嚴格使用KVC模式訪問屬性。 您可能會猜到,該屬性名為"signatureImage" ,我在#define常數kSignatureImage定義了該kSignatureImage

這是從核心數據還原映像的位置:

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

同樣, self是視圖控制器, signatureCanvasUIImageView子類, .image是其常規image屬性,繼承自UIImageView detailItemdetailItem是通常的NSManagedObject

該示例取自我當前正在處理的項目。

將大型數據對象(例如圖像)存儲在核心數據中或將它們分隔在文件中有優缺點。 將它們存儲在文件中意味着您有責任在刪除相關數據對象時刪除它們。 這提供了編碼開銷,並且對於編程錯誤可能是易變的。 另一方面,它可能會降低基礎數據庫的速度。 對於這種方法,我還沒有足夠的經驗可以與我分享。 最后,占用的磁盤存儲空間總計大致相同。

可以將圖像作為UIImage存儲在Core Data中。 盡管這不被認為是一種好習慣,因為數據庫並不用於存儲文件。 我們不使用核心數據直接存儲圖像,而是使用文件路徑存儲圖像數據到手機上。

無論如何,下面展示了我在開發附帶項目時發現的最佳方法

  1. 將實體codeGen設置為Manual / None

  2. 選擇要為圖像類型的屬性,然后選擇可變形的類型

  3. 輸入自定義類標識符作為UIImage

  4. 轉到編輯器,然后選擇創建NSManagedObject子類。

  5. 該流程將根據您的實體數量創建2個swift文件(我只有1個實體)。 現在,選擇<EntityName> + CoreDataProperties.swift文件並導入UIKit

如果在@NSManaged公共var UIImage definition上單擊“ 跳轉到定義” ,則說明您的工作已完成。

就像您對實體執行操作一樣,您可以通過向下轉換<EntityName>?.value(forKey: "<attributeName>") as? UIImage來獲取,保存和編輯圖像屬性<EntityName>?.value(forKey: "<attributeName>") as? UIImage <EntityName>?.value(forKey: "<attributeName>") as? UIImage

我不得不將實體用作NSManagedObject類型,並且由於某種原因無法直接從創建的子類訪問圖像。

我不知道為什么要在核心數據中存儲圖像,而iOS中還有其他持久存儲。 如果僅出於存儲目的而存儲圖像,則可以將其存儲在文檔目錄或緩存目錄中。 快樂編碼...

請參閱下面的URL,如何在文檔目錄中存儲和檢索圖像。

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

將圖像保存到“文檔”目錄並檢索電子郵件附件

如何使用Cocoa創建臨時文件?

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM