开发者

if statement fails with variable from CoreData managed object

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 NSNumbers (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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜