web-dev-qa-db-ja.com

コアデータに画像を保存する方法

私はiOSが初めてです。カメラからキャプチャした画像をCoreDataに保存するアプリケーションを作成しようとしています。 NSStrings、NSDateなどのデータを保存する方法を知っていますが、画像の保存に苦労しています。ディスクに書き込み、ファイルに書き込む必要があるという記事をたくさん読んでいますが、理解できないようです。

次のコードは、他のデータをコアデータに保存するために使用するコードです。

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

Binary Data属性タイプを使用して、Core Dataに画像を保存できます。ただし、いくつかの点に注意する必要があります。

  • UIImageを常にpngやjpgなどのポータブルデータ形式に変換します。例:

    NSData *imageData = UIImagePNGRepresentation(image);

  • この属性で「外部ストレージを許可する」を有効にします description Core Dataは、特定のしきい値に達するとデータを外部ファイルに移動します。このファイルもCore Dataによって完全に管理されているため、心配する必要はありません。

  • パフォーマンスの問題が発生した場合は、バイナリデータ属性を別のエンティティに移動してみてください。

  • NSManagedObjectサブクラスのインターフェースの背後でNSDataへの変換を抽象化する必要があります。そのため、UIImageからNSDataへの変換、またはその逆について心配する必要はありません。

  • 画像がモデルのエンティティに強く関連していない場合、Core Dataの外部に保存することをお勧めします。

165
jansenmaarten

XcdatamodelIdサブクラスでは、画像エンティティをNSData...として宣言します。画像データはバイナリ形式であるため、UIImage形式は使用できません。

@property (nonatomic, retain) NSData *imag;

実装ファイルで.UIImageNSDataに変換します

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

NSData *dataImage = UIImageJPEGRepresentation(sampleimage, 0.0);

そして最後に保存します

[obj setValue:dataImage forKey:@"imageEntity"]; // obj refers to NSManagedObject
12
Jemythehigh
- (void)imageChanged:(UIImage*)image{

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

これは非常に簡単な例です。 selfはコアデータを使用するView Controllerであり、self.detailItemは通常のNSManagedObjectです。そのプロジェクトでは、エンティティのモデルクラスを作成しませんでしたが、属性にアクセスするにはKVCパターンを厳密に使用しました。ご想像のとおり、属性の名前は"signatureImage"で、#define constant kSignatureImageで定義しました。

これは、イメージがコアデータから復元される場所です。

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

繰り返しますが、selfはView Controller、signatureCanvasUIImageViewサブクラス、.imageimageから継承された通常のUIImageViewプロパティです。 detailItem、これも通常のNSManagedObjectです。

この例は、現在取り組んでいるプロジェクトから取ったものです。

コアデータに画像のような大きなデータオブジェクトを保存したり、それらをファイルに分けたりすることには長所と短所があります。それらをファイルに保存するということは、関連するデータオブジェクトが削除されたときにそれらを削除する責任があるということです。これにより、コーディングのオーバーヘッドが発生し、プログラミングエラーが発生する場合があります。一方、基になるデータベースの速度が低下する可能性があります。パフォーマンスに関して共有できるこのアプローチの経験はまだ十分ではありません。最終的に、占有されるディスクストレージは合計でほぼ同じサイズになります。

4
Hermann Klecker

Swift 5およびSwift 4.2の場合

  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)")
    }
    
4
nomnom

UIImageとしてCore Dataに画像を保存することが可能です。データベースはファイルを保存するためのものではないため、これは良い習慣とは見なされませんが。コアデータを使用して画像を直接保存するのではなく、携帯電話の画像データが保存されている場所へのファイルパスを使用します。

とにかく、サイドプロジェクトの開発中に見つけた最良の方法を以下に示します

  1. エンティティcodeGenをManual/Noneに設定

  2. 画像タイプにする属性を選択し、タイプとして transformable を選択します

  3. IImageとしてカスタムクラス識別子を入力

  4. エディターに移動し、 NSManagedObjectサブクラスの作成 を選択します

  5. プロセスは、エンティティの数に応じて2つのSwiftファイルを作成します(エンティティは1つしかありませんでした)。ここで、<EntityName> + CoreDataProperties.Swiftファイルを選択し、 IKitのインポート

@NSManaged public var UIImage definition定義へのジャンプ をクリックすると、作業が完了します。

エンティティに対してアクションを実行し、<EntityName>?.value(forKey: "<attributeName>") as? UIImageをダウンキャストすることで、イメージ属性を取得、保存、編集できます。

エンティティをNSManagedObjectタイプとして使用する必要があり、何らかの理由で、作成されたサブクラスから直接イメージにアクセスできませんでした。

1
Utkarsh Jaiswal
1
Devang

IOSには他の永続ストレージが利用できるのに、なぜコアデータに画像を保存したいのかわかりません。キャッシュ目的で画像を保存するだけの場合は、ドキュメントディレクトリまたはキャッシュディレクトリに保存できます。ハッピーコーディング...

以下のURL、ドキュメントディレクトリで画像を保存および取得する方法を参照してください。

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

画像をドキュメントディレクトリに保存し、電子メールの添付ファイルを取得する

Cocoaで一時ファイルを作成する方法

0
Mangesh