Null Detection in Xcode with sqlite - objective-c

I'm writing some code here, and I'm having a had time.
I have a value in my Database that can be null as its an average of other data, if that data hasn't been populated there is nothing to take the average of.
In my query there will return a null value at times. The value that would be there normally is a double. SO i have
NSNumber *num = [NSNumber numberWithDouble:sqlite3_column_double(compiledStatement,7)];
if (num == nil) {
// do something
}
else {
// do something else
}
For some reason it is defualting to 0. When i NSLog it, it is 0, But using terminal, i'm able to be certain that my query (through terminal) is returning null for that value.
Any help would be greatly appreciated!
Thanks Guys!

By calling [NSNumber numberWithDouble:] you are guaranteeing that you get an NSNumber back. If you want to check for null, you have to do it separately, perhaps by calling sqlite3_column_type() and checking for SQLITE_NULL. Something like:
if ( sqlite3_column_type(compiledStatement, 7) != SQLITE_NULL )
{
NSNumber *num = [NSNumber numberWithDouble:sqlite3_column_double(compiledStatement,7)];
}

Related

Comparison between pointer and int (id to int) - Object wrapping still doesn't work [duplicate]

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
}

Objective-C: Test for nil/0 value?

When I log a variable that is supposed to be an NSNumber it gives me 0. I think this means it is nil and I want to exclude this case. If it is zero, I also want to exclude it. I only want to identify cases where there is a number as in 1,2,3.
However, I have tried the following and none of them succeed in excluding the case where the variable logs to 0 but include cases where it logs to 1,2,3 et. Can anyone suggest what I am doing wrong.
if (self.number!=nil) //fails to exclude
if (self.number) //fails to exclude
if (self.number.length>0)//returns error
if (self.number!=nil&&self.number!=0) //fails to exclude
of note if (!self.number) //does exclude but it also excludes case where self.number is 2, 3 or any other number.
Thanks for any suggestions
To test 0 value, try this:
NSNumber *num=[NSNumber numberWithInt:0]; or #(0);
if ([num intValue]==0 ) {
NSLog(#"number is 0"); //executes
}
NSNumber *num=[NSNumber numberWithInt:1]; or #(1);
if ([num intValue]==1 ) {
NSLog(#"number is 1"); //executes
}
same for 2 and 3 also
An NSNumber is an object wrapper around a value. You can compare it to nil, and that is appropriate, but after you've determine it is not nil you need to invoke a method on it to get the actual value it represents.
if (self.number != nil) {
NSLog(#"Number value: %ld", self.number.integerValue);
}

Comparing NSNumber to 0 not working?

I have a JSON parser in my app, and I load the value into a detailDataSourceDict variable. When I try to get the valueForKey of the array and try to compare it to 0, it never works...
Here's my code:
if (indexPath.row == 1) {
NSNumber *rating = [detailDataSourceDict valueForKey:#"rating"];
NSLog(#"Rating: %#",rating);
if (rating == 0) {
cell.detailTextLabel.text = #"This sheet has not yet been rated.";
}
else {
cell.detailTextLabel.text = [NSString stringWithFormat:#"This sheet has a %# star rating.",rating];
}
cell.textLabel.text = #"Rating";
}
I see in my JSON feed that "rating":"0", but when the rating is 0, it shows "This sheet has a 0 star rating.", instead of "This sheet has not yet been rated."
Any suggestions? Thanks.
NSNumber *rating is an object. 0 is a primitive type.
Primitive types can be compared with ==. Objects cannot; they need to be compared for equality using isEqual:.
Thus replace this:
rating == 0
with:
[rating isEqual:#0]
(#0 being a NSNumber literal)
or alternatively:
rating.integerValue == 0
The reason why your wrong code even compiles is that 0 is equal to 0x0 which in turn is equal to nil (kind of, sparing the details).
So, your current code would be equivalent to this:
rating == nil
rating is a pointer to an NSNumber object, if you compare with == 0, you'll be comparing the pointer only.
If you want to compare the value with 0, you'll have to get the actual value using intValue, try;
if ([rating intValue] == 0) {
NSNumber is an object and you have to access it's value with the value accessors.
[NSNumber intValue];
See "Accessing Numeric Values" #:
https://developer.apple.com/library/mac/#documentation/Cocoa/Reference/Foundation/Classes/NSNumber_Class/Reference/Reference.html
You want to change it from:
if (rating == 0) {
To
if ([rating intValue] == 0) {

convert id into enum using objective-c

I am trying to implement a simple method, however I am still quite a newbie on objective-c.
I have this simple method which is trying to convert from an id to a specific value in enum, if matched.
This is the enum
typedef enum {
DXTypeUnknown = 0,
DXDatasource = 1,
DXGroup = 2
} DXPropertyType;
And this is the relevant method:
-(DXPropertyType)typeFromObject:(id)_type {
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return [NSNumber numberWithInt:DXDatasource];
case DXGroup:
return [NSNumber numberWithInt:DXGroup];
default:
return [NSNumber numberWithInt:DXTypeUnknown];
}
}
The very first check I would to implement is if the id can be converted to an int, then see if it falls in the two relevant categories group or datasource, or return a default value if not. Could you tell me if the switch/case I implemented is a proper solution or not ?
I would like also this method not to causing crash of an application, so what could be advisable to check, keeping in mind that in any case the default value is to be returned.
thanks
[EDIT]
I forgot to say that this value is going to be stored in a field of a NSManagedObject, which by CoreData restriction can be an NSNumber, so probably there's a better solution instead of an enum.
It might be a good idea to include this code to check if the id can be used:
if (![_type respondsToSelector:#selector(intValue)])
return nil;
However, if you'll always pass a NSNumber go ahead and declare the method as:
- (DXPropertyType)typeFromObject:(NSNumber)_type;
In your code, you're returning a NSNumber. I don't think that's what you really
want, as you'd be doing nothing with the NSNumber passed. Return the enum
item:
-(DXPropertyType)typeFromObject:(id)_type {
if (![_type respondsToSelector:#selector(intValue)])
return nil;
int _t = [_type intValue];
switch (_t) {
case DXDatasource:
return DXDatasource;
case DXGroup:
return DXGroup;
default:
return DXTypeUnknown;
}
}
And then this can be simplified to:
- (DXPropertyType)typeFromObject:(id)_type {
if ([_type respondsToSelector:#selector(intValue)]) {
int t = [_type intValue];
DXPropertyType property_t;
if (t >= 1 && t <= 2)
property_t = t;
else
property_t = DXTypeUnknown;
return property_t;
}
return nil;
}
Your switch statement is a good solution and will not cause a crash.
However, your method returns a NSNumber when it expects a different return. I suggest changing the method to
-(NSNumber)typeFromObject:(id)_type
You specify that your method returns an enum, but you return objects. So either return the enum values or specify the return type to be NSNumber *.
A different solution could be using singleton objects instead of an enum, but that's probably more work than it's worth. Think [NSNull null].

Objective-C Condtions operators weirdness

Okay here's the damned thing:
- (void)setMinimumNumberOfSides:(NSNumber *)newMinimumNumberOfSides {
if (newMinimumNumberOfSides != minimumNumberOfSides) {
NSNumber *minimum = [[NSNumber alloc] initWithInt:(int)2];
if (newMinimumNumberOfSides > minimum) {
[newMinimumNumberOfSides retain];
[minimumNumberOfSides release];
minimumNumberOfSides = newMinimumNumberOfSides;
} else {
NSLog(#"setMinimumNumberOfSides: Invalid number of sides: %# is smaller than the minimum of %# allowed.",
newMinimumNumberOfSides, minimum);
}
[minimum release];
[newMinimumNumberOfSides release];
}
}
There's something weird going on in there! The problem is my if (newMinimumNumberOfSides > minimum) {} condition. Even if newMinimumNumberOfSides is greated than minimum it goes into the else statement.
I did:
NSNumber *minimum = [[NSNumber alloc] initWithInt:(int)6];
[polygon setMinimumNumberOfSides:minimum];
which is way greater than 2. And I receive my error message...
I tried to NSLog those two, and it gives me the right numbers... So what's going on with this?
Thanks a lot!
I think you need to change your if statement to:
if ([newMinimumNumberOfSides intValue] > [minimum intValue])
NSNumber is an object, so you have to get its integer value before you can start using it in comparisons.
You need to use the following method to compare NSNumber objects:
- (NSComparisonResult)compare:(NSNumber *)aNumber
but better yet just convert them to c ints: [myNSNumberValue inValue]