开发者

if statement fails with variable from CoreData managed object

开发者 https://www.devze.com 2023-03-18 15:07 出处:网络
I\'m having some trouble with Managed Objects... imagine that. Here is one real doozy, maybe someone can help.

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

精彩评论

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