Использование подклассов NSManagedObject для передачи постоянных и непостоянных данных

У меня есть некоторые мысли о том, как использовать подклассы NSManagedObject некоторых основных данных для обработки постоянных и непостоянных данных.

Допустим, у вас есть приложение с рецептами, отображающее список ваших собственных рецептов из CoreData, и в этом же приложении вы также можете искать рецепты других пользователей. Эти рецепты других пользователей, конечно же, взяты из API, и мы не хотим сохранять их в основных данных. Но вместо этого мы хотим, чтобы наша деталь рецепта View Controller действовала одинаково, будь то постоянный или непостоянный рецепт. Я, естественно, думаю, что тогда мы должны использовать ту же объектную оболочку для наших данных и позволить нашему контроллеру представления не замечать происхождение данных.

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

У меня есть несколько решений, но мне бы очень хотелось узнать, что вы, ребята, думаете об этой проблеме.

Можете ли вы сказать, что это проблема реализации, и ее следует решить путем объединения обоих объектов данных в один объект? Например, переопределив все методы получения и установки для обработки как объектов coredata, так и объектов NSDictionary?

Или это проблема архитектуры, и вы могли бы решить ее, например, вложив NSManagedContext или используя несколько постоянных хранилищ (одно в памяти, а другое - в Sqlite)?


person Iman Zarrabian    schedule 11.04.2013    source источник


Ответы (3)


Фактически вы можете создавать экземпляры NSManagedObject, не вставляя их в контекст. Просто передайте nil в качестве аргумента контекста управляемого объекта. Сделайте что-нибудь вроде:

NSEntityDescription *myRecipeEntity = [NSEntityDescription entityForName:@"MyRecipeEntity" inManagedObjectContext:[self managedObjectContext]];
MyRecipeClass *recipe = [[MyRecipeClass alloc] initWithEntity:myRecipeEntity insertIntoManagedObjectContext:nil]];

Теперь у вас есть экземпляр рецепта, который не находится ни в каком контексте.

Если позже вы захотите добавить его в контекст:

[[self managedObjectContext] insertObject:recipe];

Если вы не хотите его вставлять, просто выбросьте его.

person Tom Harrington    schedule 11.04.2013
comment
Насколько мне известно, у вас не может быть отношений между объектами, которые не вставлены в контекст. - person svena; 11.04.2013
comment
Конечно. Но это не всегда имеет значение. - person Tom Harrington; 12.04.2013
comment
Спасибо, это может быть решением ... Я попробую и дам вам знать, ребята - person Iman Zarrabian; 12.04.2013
comment
Эй, похоже, это действительно работает, и вы правы, в моем случае отсутствие отношений с временными объектами на самом деле не имеет значения. Кстати, initWithEntity: insertIntoManagedObjectContext: кажется методом экземпляра, а не методом класса, и его можно использовать как любой другой метод инициализации. Спасибо большое, я принимаю этот ответ прямо сейчас;) - person Iman Zarrabian; 12.04.2013
comment
Я написал демонстрацию для этого на OSX, и у меня были проблемы, когда атрибуты не сохранялись (см. github.com/seltzered/ CoreDataMagicalRecordTempObjectsDemo). Из моих результатов кажется, что использование дочернего контекста является более безопасным подходом, как предлагается в аналогичном вопросе - stackoverflow.com/a/14494126/ 314780 - person Vivek Gani; 24.06.2014
comment
Неисправная версия содержится где-нибудь в этом проекте? Нет причин, по которым использование Core Data с описанным выше подходом не привело бы к сохранению атрибутов. Не видя кода, невозможно сказать, почему это не сработало для вас, но возможно, что это побочный эффект добавления Magical Record. - person Tom Harrington; 24.06.2014
comment
Да, мой подход к использованию объекта с нулевым контекстом, а затем его вставки в контекст по умолчанию - это выделенный раздел: github.com/seltzered/CoreDataMagicalRecordTempObjectsDemo/blob/, извиняюсь за то, что просто поспешно выбросил все это в applicationDidFinishLaunching. - person Vivek Gani; 25.06.2014

Скорее всего, я бы просто использовал отдельный контекст, который вы никогда не сохраняете, это, кажется, самый простой путь.

person Chris Wagner    schedule 11.04.2013

Конфигурации модели - хранилище в памяти и хранилище с поддержкой sqlite.

Я бы серьезно рассмотрел возможность использования конфигураций модели и двух постоянных типов хранилищ: в памяти и с поддержкой sqlite.

Но это также означает, что вам придется создавать отдельные сущности для загружаемых данных, что как бы сводит на нет идею о том, что вы можете иметь некоторые рецепты постоянными, а некоторые временными, пока они оба являются рецептами. Кроме того, у вас не может быть отношений между сущностями в разных постоянных хранилищах. Вы откажетесь от преимущества обратных отношений, и вам придется имитировать это, например, с помощью извлеченных свойств.

В общем, это жизнеспособный выбор с некоторыми недостатками.

Изолированный контекст управляемого объекта

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

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

person svena    schedule 11.04.2013