I'm having some trouble with Managed Objects... imagine that.
Here is one real doozy, maybe someone can help.
So I have a managed object class called "Format" which is an entity. Anyway, it has a property called "slot" that's an NSNumber. Now the number can have values from zero to four, but if it does not have a value then I want the NSNumber object to be equal to "nil" as opposed to zero. I wasn't having any luck with that since evidently being zero is the same as being "nil." Ugh. (Is there a way to tell if the pointer is simply empty, "开发者_运维技巧nil," as opposed to pointing to a zero value?)
At any rate, I tried a work-around which was to render the variable into text like so:
if(@"myFormat.slot" != @"(null)")
NSLog(@"slot==%@",myFormat.slot);
But the problem is that I got this in my log:
slot==(null)
So, OK... what the heck? If @"myFormat.slot" == @"(null)" then how the heck is that if statement resolving...?!?!
I'm truly baffled now... please someone help me out.
You won't ever get a nil
back from an attribute. Instead, you get a [NSNull null]
object.
In Objective-C, nil
and null
are not interchangeable. When you see nil
you are almost looking at a dereferenced pointer. nil
is intended to convey that no object has been assigned to the symbol. null
by contrast is the singleton instance of [NSNull null]
. It is used as a placeholder to indicate that some value, represented by an object, has not been set. In other words, a value of nil
doesn't make sense in Objective-C.
In Core Data, relationships and attributes are not treated the same even though they both return objects. A relationship is a pointer to an external object and therefore can have a return nil
if no object has been set on the other side of the relationship. An attribute is a value only held by an object and therefore is always represented by [NSNull null]
if not set.
By default, all attributes with numerical value will return an NSNumber object initialized to zero. If you remove the default you get [NSNull null]
.
However, since [NSNull null]
is a singleton you can use a simple pointer comparison to check for it e.g.
if (myMo.numericalAttribute == [NSNull null])...
However, that is considered bad practice.
This if(@"myFormat.slot" != @"(null)")
is always true, because @"myString"
creates an autoreleased string. Therefore you are checking the addresses of to different autorelease strings and (surprise) they are different.
Have you tried something like this:
if ([myNumber isEqualTo: [NSNumber numberWithInt: 0]]) self.myNumber = nil;
When comparing the contents of 2 NSString
objects, use the isEqual:
method or, if you need to perform a Unicode-based comparison of strings, use isEqualToString:
.
If you want to set myFormat.slot
to nil
, do this:
myFormat.slot = nil;
To set the value of the slot
attribute to zero:
myFormat.slot = [NSNumber numberWithInt:0];
To compare values wrapped in NSNumber
s (e.g. check if your slot is equal to the 0 integer value), do this:
if ([myFormat.slot intValue] == 0) { // primitive type comparison
//...
}
or this:
if ([myFormat.slot isEqual:[NSNumber numberWithInt:0]]) { // object comparison
//...
}
but NOT THIS:
if (myFormat.slot == 0) { // pointer comparison!!
//...
}
To check if slot
is empty (nil):
if (myFormat.slot == nil) {
//...
}
Keep in mind: Core Data standard attributes are always mapped to non-primitive values (NSString, NSDate, NSNumber). Always use isEqual:
, compare:
& friends when comparing objects' values. The ==
operator performs pointer comparison when you use it with non-primitives.
精彩评论