views:

66

answers:

1

After migration, one of my numerical values that should be non-zero now appears as zero. If I don't migrate, the value retains its non-zero value.

I first tried to set a number value in a managed object like this:

[temp setNumUses:temp.numUses+1];

... but that caused an'EXC_BAD_ACCESS' so I changed it to:

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

... but after migration, this code claimed that hold was initialized as an int with a value of 0 when before running the new code its value was clearly 1 or more (referring to the test object which was used only 1 time).

When I do not migrate the Core Data Database the NSNumber retains its value fine through many context saves and application terminations.

What might I be missing? I have some extensive code that modifies values of changed NSManagedObjects in a database stored elsewhere but none of it tampers with 'numUses'.

Thoughts?

A: 

The simplest explanation is that the migration somehow convinces Core Data that numUses is a new attribute with default value of zero. The reason for this would be in the migration model and not in the assignment code you have provided.

However, the code in the parent does suggest you don't quite understand NSNumber and miss using NSNumber elsewhere might cause your problem.

NSNumber is only an object wrapper around numerical values. You can't perform operations with it. That is why this line:

[temp setNumUses:temp.numUses+1];

... causes the EXC_BAD_ACCESS. As you discovered, you have to convert a NSNumber to an int or NSDecimalNumber to perform mathematical operations on it.

This line:

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

... will leak memory. You initialize a NSNumber object but never release it. In this case (and the vast majority of all cases), you should use the class methods to create NSNumbers because they return an autoreleased object that won't leak. So:

[temp setNumUses:[NSNumber numberWithInt:hold];

In general, it is bad practice to initialize any object in a method parameter. You are asking for nasty memory leaks that will be very hard to track down. The report of the leak may not show up in the code where the method is called but in the method itself.

TechZen
Hi, I would like to point out that I am relatively new at programming with Objective-C. I did try the NSNumber class method before the allocation but I wanted to cover all my bases just to be sure. Still got the problem of the NSNumber value being 0 either way. Are there any tips you can give me on Core Data Migration Models? To migrate the database in my code I simply followed a guide to adding automatic migration, is there a better way/easy way to fix this problem using that method still?
Also, why would: [temp setNumUses:temp.numUses+1]; end up working? I wrote that code awhile ago which has since been replaced but it did work before migration. Are there operator methods written into NSNumber? Or do these not exist? Thanks!
NSNumber has no operator methods. You can't just add a scalar to an NSNumber object. If you try, you will actually increment the address of the object. I don't know why your migration is failing.
TechZen
Is there a guide you can point me to for properly migrating a Core Data Database?