Как сохранить изображение в основных данных

Я новичок в iOS. Я пытался создать приложение, которое сохранит изображение, снятое с камеры, в CoreData. Теперь я знаю, как хранить данные типа NSString s, 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];
} 

Ответ 1

Вы можете хранить изображения в базовых данных с использованием типа атрибута Binary Data. Однако вы должны знать несколько вещей:

  • Всегда конвертируйте свой UIImage в переносимый формат данных, например png или jpg Например:

    NSData *imageData = UIImagePNGRepresentation(image);

  • Включить "Разрешить внешнее хранилище" в этом атрибуте description Core Data переместит данные во внешний файл, если он достигнет определенного порога. Этот файл также полностью управляется Core Data, поэтому вам не нужно беспокоиться об этом.

  • Если вы столкнулись с проблемами производительности, попробуйте переместить атрибут Binary Data в отдельный объект.

  • Вы должны абстрагировать преобразование в NSData за интерфейсом вашего подкласса NSManagedObject, поэтому вам не нужно беспокоиться о конверсиях из UIImage в NSData или наоборот.

  • Если ваши изображения не сильно связаны с объектами в вашей модели, я бы предложил хранить их вне Core Data.

Ответ 2

В подклассе xcdatamodelI объявляет объект изображения как NSData... вы не можете использовать формат UIImage, потому что данные изображения находятся в двоичном формате.

@property (nonatomic, retain) NSData *imag;

В файле реализации.. convert UIImage to NSData

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

NSData *dataImage = UIImageJPEGRepresentation(sampleimage, 0.0);

Затем, наконец, сохраните его

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

Ответ 3

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

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

В этом очень краткий пример. self - это контроллер представления с использованием данных ядра, а self.detailItem - обычный объект NSManagedObject. В этом проекте я не создавал классы моделей для объектов, но строго использовал шаблон KVC для доступа к атрибутам. Как вы могли догадаться, атрибут имеет имя "signatureImage", которое я определил в константе #define kSignatureImage.

Здесь изображение восстанавливается из основных данных:

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

Опять же, self является контроллером представления, signatureCanvas является подклассом UIImageView, а .image является его обычным свойством image, унаследованным от UIImageView. detailItem, опять же, является обычным NSManagedObject.

Пример берется из проекта, над которым я сейчас работаю.

Есть плюсы и минусы для хранения больших объектов данных, таких как изображения в основных данных, или их разделение в файлах. Сохранение их в файлах означает, что вы несете ответственность за их удаление при удалении связанных объектов данных. Это обеспечивает накладные расходы на кодирование и может быть изменчивым для ошибок программирования. С другой стороны, это может замедлить базовую базу данных. У меня еще недостаточно опыта с этим подходом, который я мог бы рассказать в отношении производительности. В итоге занимаемая память диска примерно равна одному и тому же размеру.

Ответ 5

Для Swift 5 и Swift 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)")
    }
    

Ответ 6

Я не знаю, почему вы хотите хранить изображение в основных данных, тогда как в iOS есть другое постоянное хранилище. Если вы хотите сохранить изображение для цели кеша, его можно сохранить в каталоге документа или в кеше. Счастливое кодирование...

См. ниже URL-адрес, Как сохранять и извлекать изображения в каталоге документа.

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

Сохранение образа в папке Документы и извлечение для вложения электронной почты

Как создать временный файл с Cocoa?

Ответ 7

Можно хранить изображения в Core Data как UIImage. Хотя это не считается хорошей практикой, поскольку базы данных не предназначены для хранения файлов. Мы не используем основные данные для непосредственного хранения изображений, вместо этого мы используем путь к файлу, в котором хранятся данные изображений на вашем телефоне.

В любом случае, лучший метод, который я нашел при разработке стороннего проекта, показан ниже.

  1. Установите для CodeGen объекта значение Manual/None

  2. Выберите атрибут, который вы хотите, чтобы иметь тип изображения и выберите трансформируемый в качестве его типа

  3. Введите идентификатор пользовательского класса как UIImage

  4. Зайдите в редактор и выберите Создать NSManagedObject Subclass

  5. Процесс создаст 2 быстрых файла в зависимости от количества ваших объектов (у меня был только 1 объект). Теперь выберите <EntityName> + CoreDataProperties.swift и импортируйте UIKit

Если при нажатии Перейти к определению для определения @NSManaged public var UIImage definition ваша работа завершена.

Выполните действия с объектами так же, как и вы, и вы сможете получать, сохранять, редактировать атрибут изображения, <EntityName>?.value(forKey: "<attributeName>") as? UIImage <EntityName>?.value(forKey: "<attributeName>") as? UIImage.

Мне пришлось использовать сущность в качестве типа NSManagedObject и по какой-то причине не смог получить доступ к изображению напрямую из созданного подкласса.