Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Storing optional NSNumber in Core Data

In my core data model, I have an entity with an optional NSNumber attribute.

How do I test to see if the value in that attribute is valid or not?

When I test for nil... doesn't work.

[self numberAttribute] == nil // always returns NO

When I test for a zero value int, that doesn't work.

[[self numberAttribute] intValue] == 0  // always returns no

As a matter of fact, [[self numberAttribute] intValue]] returns something that looks suspiciously like a pointer to a memory address.

Anyone have any idea what I am doing wrong?

EDIT: OK, the bug was in a totally unrelated part of the code. NSNumber and Core Data are functioning exactly as one would expect. That said, I am going to go with the suggested approach of making the attribute non-optional and specifying 0 as the default value.

Just putting this note here for a little while for anyone who was watching this question, then I am deleting it.

like image 779
mmc Avatar asked Jul 27 '09 14:07

mmc


1 Answers

According to the documentation,

You can specify that an attribute is optional—that is, it is not required to have a value. In general, however, you are discouraged from doing so—especially for numeric values (typically you can get better results using a mandatory attribute with a default value—in the model—of 0). The reason for this is that SQL has special comparison behavior for NULL that is unlike Objective-C's nil. NULL in a database is not the same as 0, and searches for 0 will not match columns with NULL.

false == (NULL == 0)
false == (NULL != 0)

Moreover, NULL in a database is not equivalent to an empty string or empty data blob, either:

false == (NULL == @"")
false == (NULL != @"")

So, try a test with NULL, which is not nil. Better yet, set a default and change the attribute to be non-optional. That's what I've ended up doing in my models, and in practice it works quite well.

Edit: See my comment above. I tried creating a new managed object with an optional attribute not set, and it was nil.

BOOL isNil = ([newManagedObject numberAttribute] == nil);  //equals YES

Another edit: I came back to this later and checked out an object loaded from the cache in the debugger (gdb is your friend!). It was trying to access memory location 0x0, which is NULL.

like image 184
Don Avatar answered Sep 22 '22 21:09

Don