Core Data Migration теряет значение NSNumber

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

Сначала я попытался установить числовое значение в управляемом объекте следующим образом:

[temp setNumUses:temp.numUses+1];

... но это вызвало «EXC_BAD_ACCESS», поэтому я изменил его на:

int hold = ((int)[[temp valueForKey:@"numUses"] intValue]);
hold++;
[temp setNumUses:[[NSNumber alloc] initWithInt:hold]];

... но после миграции этот код утверждал, что hold был инициализирован как int со значением 0, когда перед запуском нового кода его значение было явно 1 или более (имеется в виду тестовый объект, который использовался только 1 раз).

Когда я не переношу базу данных Core Data, NSNumber прекрасно сохраняет свое значение при многих сохранениях контекста и завершении приложений.

Что я могу упустить? У меня есть обширный код, который изменяет значения измененных NSManagedObjects в базе данных, хранящейся в другом месте, но ни один из них не вмешивается в «numUses».

Мысли?


person Kristian K    schedule 26.09.2010    source источник


Ответы (1)


Самое простое объяснение состоит в том, что миграция каким-то образом убеждает Core Data в том, что numUses — это новый атрибут со значением по умолчанию, равным нулю. Причина этого кроется в модели миграции, а не в предоставленном вами коде назначения.

Однако код в родительском элементе предполагает, что вы не совсем понимаете NSNumber, и отсутствие использования NSNumber в другом месте может вызвать вашу проблему.

NSNumber — это всего лишь оболочка объекта для числовых значений. Вы не можете выполнять операции с ним. Вот почему эта строка:

[temp setNumUses:temp.numUses+1];

... вызывает ошибку EXC_BAD_ACCESS. Как вы обнаружили, вам нужно преобразовать NSNumber в int или NSDecimalNumber, чтобы выполнить над ним математические операции.

Эта строка:

[temp setNumUses:[[NSNumber alloc] initWithInt:hold]];

... приведет к утечке памяти. Вы инициализируете объект NSNumber, но никогда не выпускаете его. В этом случае (и подавляющем большинстве всех случаев) вы должны использовать методы класса для создания NSNumbers, потому что они возвращают автоматически выпущенный объект, который не будет протекать. Так:

[temp setNumUses:[NSNumber numberWithInt:hold];

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

person TechZen    schedule 26.09.2010
comment
Привет, я хотел бы отметить, что я относительно новичок в программировании с помощью Objective-C. Я попробовал метод класса NSNumber перед выделением, но я хотел охватить все свои базы, чтобы быть уверенным. Все еще есть проблема со значением NSNumber, равным 0 в любом случае. Есть ли какие-либо советы, которые вы можете дать мне по основным моделям миграции данных? Чтобы перенести базу данных в свой код, я просто следовал руководству по добавлению автоматической миграции, есть ли лучший/простой способ решить эту проблему, используя этот метод? - person Kristian K; 27.09.2010
comment
Кроме того, почему: [temp setNumUses:temp.numUses+1]; в итоге работать? Я написал этот код некоторое время назад, который с тех пор был заменен, но он работал до миграции. Существуют ли операторные методы, записанные в NSNumber? Или таких нет? Спасибо! - person Kristian K; 27.09.2010
comment
NSNumber не имеет методов операторов. Вы не можете просто добавить скаляр к объекту NSNumber. Если вы попытаетесь, вы фактически увеличите адрес объекта. Я не знаю, почему ваша миграция не удалась. - person TechZen; 28.09.2010
comment
Есть ли руководство, на которое вы можете мне указать, для правильной миграции базы данных Core Data? - person Kristian K; 28.09.2010