Objective-C: Test for nil/0 value? - objective-c

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);
}

Related

Does -[NSOrderedSet indexesOfObjectsPassingTest:] really return either an NSIndexSet or NSNotFound?

I have this code:
NSIndexSet *indexes = [anOrderedSet indexesOfObjectsPassingTest:^BOOL(id obj, NSUInteger idx, BOOL *stop) {
if([self testObj: obj]) return YES;
else return NO;
}];
if(indexes == NSNotFound) NSLog(#"No objects were found passing the test");
And this causes a warning from Xcode stating "Comparison between pointer and integer ('NSIndexSet *' and 'int')". And I totally agree with Xcode on this one.
However, the return value of the function is of type NSIndexSet* and the Apple documentation (http://developer.apple.com/library/ios/#documentation/Foundation/Reference/NSOrderedSet_Class/Reference/Reference.html) states:
Return Value
The index of the corresponding value in the ordered set that passes the test specified by predicate. If no objects in the ordered set pass the test, returns NSNotFound.."
So what's the deal with returning NSNotFound (which is an NSInteger) when the return type of the function is a pointer to NSIndexSet? Is it safe to suppress the warning by changing the comparison to:
if(indexes == (NSIndexSet*) NSNotFound) NSLog(#"No objects were found passing the test");
Because, theoretically, indexes could be a valid returned NSIndexSet pointer that just happens to point to a memory address equal to NSNotFound, correct?
I’m afraid the documentation is wrong.
You should check against an empty NSIndexSet:
if ([indexes count] == 0) NSLog(#"No object were found passing the test");
You should probably open a bug report with Apple.
Apparently the Apple documentation is incorrect.
In my tests, I am finding that if no objects in the ordered set pass the test, then the returned object is an NSIndexSet of count equal to zero.
Thus, the correct test is:
if(indexes.count == 0) NSLog(#"No objects were found passing the test");

Objective C NSPredicate predicateWithBlock removing nil/null values

I am trying to populate an array by taking an existing array and removing nil values from it. The array was populated from a the JSON response of an http call. Sometimes the array has a null value at the end, and the easiest way to remove that value so I wouldn't have to handle it everywhere in my code would be to use NSArray's filteredArrayUsingPredicate: to assign the variable into the instance variable I use throughout my class.
NSArray *respAgencyList = (NSArray*) [JSON valueForKeyPath:#"xml.path.to.data" ];
NSLog(#"data before filter: %#", respAgencyList);
// prints: ( { domain: "foo.com", name:"foobar"}, "<null>" });
if (respAgencyList != nil && respAgencyList.count > 0) {
agencies = [respAgencyList filteredArrayUsingPredicate:[NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
NSLog(#"Evaluated object is %#", evaluatedObject); //prints <null> for the null value
BOOL ret = evaluatedObject != nil;
return ret;
}]];
}
In the above code the return value is always YES. However, when I put the debugger on and step through it I see:
evaluatedObject = id 0x00000000
Isn't this a null/nil value? What is different about this value compared to nil?
You should also check for NSNull, which can be placed into an NSArray since it is a proper object.
BOOL ret = (evaluatedObject != nil && [evaluatedObject isKindOfClass:[NSNull class]] == NO);
It is impossible for an NSArray to contain a nil element.
Some enumeration methods do hand you nil after the enumeration, as a signal that you've reached the end, but the nil is not in the array — it's just a signal, and you are not expected to do anything serious with it. However, I do not know whether this is one of them.
I suggest that instead of trying to remove nil from the array, which is impossible since nil was never there in the first place, you examine the array directly (log it, look in the debugger, whatever) and assure yourself that what you're trying to do is unnecessary.

String compare Objective-C

I've been struggling with a simple comparison but I can't get it to work.
I´m reading a XML file and I need to compare data from it in order to show the right picture.
http://www.cleaner.se/larm.xml (Example file for parsing)
I have tried things like:
if([aLarm.larmClass isEqualToString:#"A"])
NSLog(#"same");
else
NSLog(#"Not same");
If I use: NSLog(aLarm.larmClass); console puts it out nicely as it should. What am I doing wrong?
You can use the NSString compare: methods. For example:
if ([myString caseInsensitiveCompare:#"A"] == NSOrderedSame ) {
NSLog(#"The same");
} else {
NSLog(#"Not the same.");
}
The result is an NSComparisonResult which is just an enum with types NSOrderedSame, NSOrderedAscending and NSOrderedDescending.
Check the documentation on the various compare: methods here.
Of course, if the receiver is actually an NSString, then isEqualToString: should also work. So if you're trying to compare a class name (aLarm.larmClass ??), then you can call:
if ([NSStringFromClass([aLarm class]) isEqualToString:#"A"] ) {
NSLog(#"The same");
}
If the larmClass property is a string, make sure that it is actually one character in length (i.e. it doesn't have any leading or trailing whitespace that was accidentally included when parsing the XML). If the larmClass property truly is an NSString containing the letter ‘A’ then [aLarm.larmClass isEqualToString:#"A"] will return YES.
Do a:
NSLog(#"%u, %#", [aLarm.larmClass length], aLarm.larmClass);
and just make sure that it shows “1, A”.

How to write a valid boolean conditional in objective-c using objectForKey

I'm seeking to understand why the following always hits the ELSE clause. What I can't figure out is that regardless of the actual value ( NSLog shows a 0 or 1) this always hits the else. Any reason why?
The item NSArray is pulled from a JSON object -fyi
BOOL* instock = [item objectForKey:#"itemInStock"];
obj.instock = instock;
NSLog(#"and it was %#", obj.instock);
if (obj.instock == YES) {
//do yes stuff
}else {
//do no stuff
}
Your code here is rather strange. What is the type of obj.instock? Your very first line
BOOL* instock = [item objectForKey:#"itemInStock"];
makes no sense at all. -objectForKey: doesn't return BOOL* values. It returns id. I'm guessing here that you're actually getting an NSNumber * back, and it just happens to work alright because an NSNumber * fits inside of a BOOL * (as they are both pointers). Similarly, obj.instock is likely to be an NSNumber* as well (if it wasn't an object of some sort, your NSLog() would crash).
So, assuming that obj.instock is an NSNumber*, the conditional you want is simply
if ([obj.instock boolValue]) {
// yes
} else {
// no
}
You should also fix this code to not try and claim you have a BOOL* when you don't.
In your NSLog, you are using %#.
%# refers to objects. Contrary to your BOOL* instock which is not an object.
There are ways to fix that.
What data type does your [item objectForKey:#"itemInStock"]; return?
If it returns an NSNumber for example, then you can do:
obj.instock = [[item objectForKey:#"itemInStock"] boolValue];
NSLog(#"and it was %d", obj.instock);
if (obj.instock == YES) {
//do yes stuff
}else {
//do no stuff
}
Again, there are other ways to do that.

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]