Эффективное хранение идентичных данных в модели данных Core Data
-
05-07-2019 - |
Вопрос
У меня есть модель данных, которая содержит несколько объектов, каждый с несколькими различными атрибутами, которые хранят данные изображения.Все это будут небольшие изображения, и мне нужно сохранить их в постоянном хранилище, а не как внешние файлы.
Хотя я могу просто сохранить данные изображения в двоичном или преобразуемом атрибуте, вполне вероятно, что пользователь укажет идентичные изображения для двух или более из этих атрибутов, поэтому я бы предпочел сохранить по одной копии каждого уникального изображения, а не дублировать данные изображения.
Я повозился с созданием объекта "ImageBlob" для хранения данных изображения и использованием отношений для этого, но я новичок в Core Data, и мне не сразу понятно, правильный ли это путь.В частности, как мне справляться со следующими ситуациями?
- Я хочу, чтобы все мои атрибуты изображения в нескольких объектах использовали одно и то же "хранилище данных изображения", чтобы сохранялся только один экземпляр каждого большого двоичного объекта изображения
- Мне нужно убедиться, что если никакие объекты не используют изображение в хранилище данных, то оно будет удалено
Каков был бы наилучший способ справиться с этим?
Решение
Мой первый вопрос был бы таков: как вы планируете определить, когда два объекта используют одно и то же изображение?Есть ли у изображения свойство, которое вы можете сохранить и запросить, чтобы определить, существует ли уже устанавливаемое вами изображение?И насколько это дорого с точки зрения вычислений?Если это займет много времени, вы можете в конечном итоге оптимизировать объем хранилища и повлиять на производительность.
Однако, если у вас есть способ сделать это эффективно, вы могли бы создать ImageBlob
сущность, чтобы делать то, что вы описываете.Объект , который использует ImageBlob
s должен иметь imageBlob
или imageBlobs
отношения с ImageBlob
. ImageBlob
должно иметь обратную связь с таким именем, как, например, users
.
В вашем коде, когда вы хотите повторно использовать ImageBlob
, это так же просто, как сделать что - то подобное этому:
NSManagedObject *blob = // get the image blob
NSManagedObject *user = // get the user
[user setValue:blob forKey:@"imageBlob"]; // do this if it uses a single image
[[user mutableSetValueForKey:@"imageBlobs"] addObject:blob]; // do this if it uses multiple images
Еще одно соображение, о котором вам стоит подумать, - это то, что делать с большими двоичными объектами, которые больше не нужны.Предположительно, вы хотите удалить все изображения, которые не используются.Для этого вы можете зарегистрировать своего делегата приложения или NSPersistentDocument
подкласс (в зависимости от того, основано ли ваше приложение на документах или нет) для NSManagedObjectContextObjectsDidChangeNotification
уведомление.Всякий раз, когда изменяется контекст управляемого объекта, вы можете удалять любые ненужные изображения, подобные этому:
- (void)managedObjectContextObjectsDidSave:(NSNotification *)notification {
NSManagedObjectContext *managedObjectContext = [notification object];
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
[fetchRequest setEntity:[NSEntity entityWithName:@"ImageBlob" inManagedObjectContext:managedObjectContext]];
[fetchRequest setPredicate:[NSPredicate predicateWithFormat:@"users.@count == 0"];
NSArray *unusedBlobs = [managedObjectContext executeFetchRequest:fetchRequest error:nil]; // Don't be stupid like me; catch and handle the error
[fetchRequest release];
for (NSManagedObject *blob in unusedBlobs) {
[managedObjectContext deleteObject:blob];
}
}
Другие советы
Вы могли бы добавить уникальное свойство под названием md5 к Image
Сущность, чтобы убедиться, что вы сохраняете одни и те же изображения только один раз.
Что касается основных данных, я думаю, что что-то подобное могло бы сработать:Затем создайте абстрактную родительскую сущность (Parent
).Добавьте связь из Parent
Для Image
вызванный image
, и установите "Каскад" для метода удаления , чтобы при удалении Parent
, Image
также удаляется.Добавьте связь из Image
Для Parent
вызванный parent
, или что-то еще, и установите "Nullify" для метода удаления, чтобы при удалении Image
, изображение для Parent
установлено значение nil
.Затем добавьте другие ваши объекты и установите для их родительского элемента значение Parent
.