Score is NSManagedObject. score.latitude is an NSNumber, which actually is a float value.
NSLog(#"%f", [score.latitude floatValue]);
shows 0.000000.
Construction I use to check for nil:
if (score.latitude == nil)
doesn't work.
It's irrelevant that there is a floating-point value stored in your NSNumber instance; the object itself is either nil or not. To check for an object being nil, if( obj == nil ) is functionally equivalent to if( obj ).
So your conditional may not be doing what you expect, but it is checking for nil. You'd need to add more details about what's happening in the body of the if, should you need more specific explanation.
The key point is that sending a message to nil, such as [nil floatValue] always returns 0, interpreted as whatever the return type of the method is. For example, if you send floatValue to nil, you'll get back floating-point 0. If you send a message that should return an object, you'll get nil; a message that should return an int, you get integer 0.
Also be aware that when you say if( score.latitude ), the expression will evaluate false if either score or latitude is nil (because if score is nil, sending latitude to it will return nil.)
A float can be nil, as it isn't an object.
And a NSNumber is not an float value, but has a method, that returns a float value.
use if (score) to check, if the NSNumber got instantiated before.
As I finally understand, the problem is because of Core Data save data to sql database, which stores nil properties as 0.000...
Related
So my problem is this:
I am receiving a JSON string from across the network. When decoded (using SBJSON libraries), it becomes an NSDictionary that SHOULD contain a number of some sort for the key 'userid'. I say 'should' because when I compare the value to an int, or an NSINTEGER, or NSNumber, it never evaluates correctly.
Here is the comparison in code:
NSDictionary *userDictionary = [userInfo objectAtIndex:indexPath.row];
if ([userDictionary objectForKey:#"userid"] == -1) {
//Do stuff
}
The value inside the dictionary I am testing with is -1. When I print it out to console using NSLog it even shows it is -1. Yet when I compare it to -1 in the 'if' statement, it evaluates to false when it should be true. I've even tried comparing to [NSNumber numberWithInt: -1], and it still evaluates to false.
What am I doing wrong? Thanks in advance for your help!
You are comparing a pointer to an object, not an integer itself. You must first convert the object into an integer:
if ([[userDictionary objectForKey:#"userid"] integerValue] == -1)
{
//Do stuff
}
I have a variable in core data. I want to detect for the cases where it is nil zero, null or otherwise does not have a nice value such as 222 or 333.
This should be trivial but I am getting caught up in Objective-C's syntax.
Following code is not working:
if (_item.id!=nil && _item.id!=0) {
//do something
}
Of note id should be an NSNumber.
It is defined as
#property (nonatomic, retain) NSNumber * id;
I should clarify that it is not working when the value logs to console as 0.
Given the way variable types and core data work, I cannot tell you what causes the variable to log to console as '0' but something is causing it to do so. Basically, I want to exclude cases where the value is anything other than a non-zero integer (in mathematical, not computer science terms).
To check the numeric value stored in an NSNumber, you have to call one of the methods which give you a primitive type.
e.g. integerValue, unsignedLongLongValue, doubleValue
To correctly check for nil and a value of 0, you need the following:
if (_item.id != nil && [_item.id intValue] != 0) {
// code here
}
Because sending a message to a nil reference returns 0, you can take a shortcut:
if ([_item.id intValue] != 0) ...
This works because _item.id has to be non-nil to return a non-zero value from intValue.
As this NSManagedObject is of type NSNumber, simply check the intValue.
if (!_item.id.intValue){
//Method will stop in here if the id is nil/0 etc.
}
However, it is not recommended to name a variable id, I suggest you rename it to itemId
In the same way you shouldn't name something 'string', or 'new' etc as these conflict with Apple's own native naming policies
To check the numeric value stored in an NSNumber, you have to call one of the methods which give you a primitive type.
e.g. integerValue, unsignedLongLongValue, doubleValue
To correctly check for nil and a value of 0, you need the following:
if (_item.id != nil && [_item.id intValue] != 0) {
// code here
}
Because sending a message to a nil reference returns 0, you can take a shortcut:
if ([_item.id intValue] != 0)
NSNumber *badNum = 0;
NSNumber *goodNum = #42;
if ([badNum compare:goodNum] == NSOrderedAscending)
// ...
Given the above snippet, where badNum is effectively nil, is the if statement guaranteed to never be entered?
Essentially, I want to know if I must do a nil check every time I use -[NSNumber compare:], so another question is will I need to use the following code to make sure compare always works as it appears?
if (badNum && goodNum && [badNum compare:goodNum] == NSOrderedAscending)
// ...
Yes, it is guaranteed, as long as Apple does not change NSOrderedSame, which is currently defined as zero:
enum {
NSOrderedAscending = -1,
NSOrderedSame, // == 0
NSOrderedDescending // == 1
};
The reason you appear to get NSOrderedSame when sending compare: message to nil is that Objective-C supplies the default value for the return type when the target is nil. Since NSOrderedSame is 0, the default value, you are guaranteed to get it when badNum is nil.
Here is my method createNewRectangleWithHeight and the parameter is heightParam and widthParam. My problem is i can't use the parameter in the method.
I am getting an error something like this
Bad receiver type 'NSUInteger *' (aka 'unsigned int *')
-(BOOL)createNewRectangleWithHeight:(NSUInteger *)heightParam width:(NSUInteger *)widthParam{
if ([[heightParam length] == 0] || [widthParam length]==0]) {
NSLog(#"The height and width must no be 0");
}
}
Error is in if condition
You can only call methods on objects. A pointer to an unsigned int is not an object; it's just the address of a number.
You don't need to pass addresses unless you're changing the value inside your method and you can just check the value rather than treating the number as an object.
-(BOOL)createNewRectangleWithHeight:(NSUInteger)heightParam width:(NSUInteger)widthParam {
if (heightParam == 0 || widthParam == 0) {
NSLog(#"The height and width must not be 0");
}
}
Learn to look at the error messages you get. In this case the error message is telling you exactly what's wrong. The syntax [object message] is sending a message to an object. NSInteger is a scalar type, not an object type.
BTW, your method does not return a result, and is badly named. It should be called something like heightAndWidthAreNotZero.
Others have already pointed out that you should be using (NSUInteger), not (NSUInteger *), as your parameter types. Actually, if you're getting ready to create a CGRect, you should probably be using CGFloat, not NSUInteger, since the different values of a CGRect are CGFloat type.
Finally, there is a built-in system function CGRectIsEmpty() that takes a CGRect as input and returns TRUE if the rectangle is empty, and FALSE if it's not empty.
Does the following function return YES if object != nil?
- (BOOL)boolForObject:(id)object {
return (BOOL)object;
}
I've tested with object = [[NSObject alloc] init] but got mixed results.
A pointer is larger than a BOOL, so when you cast it will truncate and take only the 8 least significant bits of the pointer and make it a BOOL. If those bits all happen to be zero then that is equivalent to NO.
So to answer your question, no it does not (well sometimes it will depending on the pointer value)
Here's an example with using Xcode 5.1.1 on 32 bit architecture:
void* p = (void*)0xfeeeff00;
BOOL b = (BOOL)p;
NSLog(#"p=%08x (%lu), b=%08x (%lu)", (uint32_t)p, sizeof p, (uint32_t)b, sizeof b);
It prints out:
p=feeeff00 (4), b=00000000 (1)
What is the actual purpose of your method?
If it's just to check whether an object is nil or not, why not do it like this:
- (BOOL)boolForObject:(id)object
{
return (object != nil);
}
It's more obvious what the result will be.
You could also do:
return !!object;
I don't think so, but
return object != nil;
will.