Вопрос создания экземпляра модели при использовании Core Data - PullRequest
2 голосов
/ 04 августа 2009

Я немного запутался в одном аспекте Core Data. То есть, когда я использую рудиментарную процедуру alloc / init против созданного объекта с основными данными и сохранения его в текущем контексте управляемого объекта.

Я знаю, что это довольно расплывчатый вопрос, поэтому позвольте мне привести пример.

У меня есть приложение, над которым я сейчас работаю, которое просматривает всю контактную книгу пользователя на iPhone. Оттуда я написал модельный класс под названием «Персона». Я делал что-то подобное в кругу людей:

Person * person = [[Person alloc] initWithWrapper: mywrapper];

mywrapper будет содержать NSDictionary с атрибутами для человека. Позже я смогу заполнить адресную книгу в моем приложении объектами person.

Теперь я начал перестраивать части приложения с помощью Core Data. Продолжаю ли я использовать приведенную выше стратегию для заполнения своей адресной книги? Или я делаю что-то вроде этого:

    Person *person = (Person *)[NSEntityDescription insertNewObjectForEntityForName:@"Person" inManagedObjectContext:managedObjectContext];

    [person setName:name];
    [person setDob:dob];

    // Commit the change.
    NSError *error;
    if (![managedObjectContext save:&error]) {
        // Handle the error.
    }

Проблема в том, что этот код выполняется при каждом запуске приложения. Не следует ли мне использовать основные данные, поскольку они будут заполнять механизм хранения избыточными экземплярами человек при каждой загрузке приложения? Должен ли я изменить свой NSManagedObject (класс Person) и добавить свой initWithWrapper: метод и продолжить, как обычно?

Немного смущен, хотел бы разъяснений.

Ответы [ 2 ]

4 голосов
/ 04 августа 2009

Вы никогда не должны инициализировать объекты Core Data вне контекста управляемого объекта - в этом просто нет смысла. Имея немного

Person *person = [[[Person alloc] init] autorelease];

не приносит вам пользы, поскольку вы не можете сохранить объект, манипулировать им или действительно сделать что-нибудь полезное, что Core Data предоставляет без контекста (и, следовательно, координатора модели и хранилища), его резервного копирования.

Вместо этого вы должны использовать комбо alloc - init только при первой вставке объекта в Core Data; для этого и используется метод initWithEntity:insertIntoManagedObjectContext:. И вы правы, каждый раз, когда вы вызываете этот метод, вы вставляете новый объект в контекст Core Data и, следовательно, сохраняете, и вы можете получить дубликаты объектов, если не будете осторожны.

Что бы я порекомендовал вам, если вы запускаете код при каждом запуске, это создать запрос Core Data, который возвращает некоторый набор существующих объектов Person, и добавлять только объекты (используя метод инициализации), которые не существует в магазине Если объект уже существует, измените его вместо создания нового.

Хитрость заключается в том, чтобы заставить что-то подобное правильно работать. Вы не должны делать выборку Core Data для каждого контакта в адресной книге iPhone; многие маленькие фишки очень дорогие. Теоретически вы можете получить два NSSets - один из объектов Person и один из контактов - затем сравнить их по некоторому уникальному ключу (например, хэш имени и фамилии контакта). Я оставляю вам оптимизацию.

Ключевой момент заключается в следующем: не используйте alloc и init для объекта Core Data, если только вы не собираетесь впервые вставить этот объект в контекст . Вместо этого посмотрите на существующие объекты и измените их при необходимости.

0 голосов
/ 04 августа 2009

Да, проще всего добавить метод initWithWrapper в ваш класс Person. Это было бы что-то вроде этого:

- (id) initWithWrapper:(NSDictionary *)wrapper {
  NSEntityDescription * person = [NSEntityDescription entityForName:@"Person" inManagedObjectContext:someMOC];
  if (self = [super initWithEntity:person insertIntoManagedObjectContext:someMOC]) {
    //do your wrapperly initialization here
  }
  return self;
}

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

При этом я все время использую этот шаблон.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...