NSNumber with IF statement issue - ios

I am loading data from a server but I have an issue that the value that I am returning is zero(0) while I can't go inside if. Please where would be the problem?
-(void)method1
{
NSNumber *value = [data objectForKey:#"samount"];
NSLog(#"number is -%#-", value); //number is -0-
if (value == 0)
{
NSLog(#" OK :) ");
}
else
{
NSLog(#" Bad :( ");
}
}

Use isEqual:
if ([value isEqual:#(0)])
That will also evaluate correctly in case value is nil (where == comparison with floatValue or similar methods would fail)

value is an object, and more precisely a NSString object (as per your comments in Alladinian's answer), but you are checking its address. You can convert your string to NSNumber with NSNumberFormatter and then check its value or rely on NSString's built-in methods: integerValue, floatValue, etc.
Assuming value is a NSNumber/NSString:
if ([value integerValue] == 0)
See Getting Numeric Values in NSString documentation and Accessing Numeric Values in the NSNumber documentation and pick the method that best suits your data type.

Related

NSNull returns <null> instead of returning null

I'm using the following code to check if a NSNumber has nil value. So I'm converting the NSNumber to string and Im checking if its length is 0. If it is of zero, Im returning NSNull else Im returning the number itself.
- (id)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return [NSNull null];
}
return number;
}
Im invoking it as follows,
NSString *bodyString = [NSString stringWithFormat:#"[ \"%#\",{\"session_token\": \"%#\",\"request\": [\"GetAssigneeWiseCompliancesChart\",{\"country_id\": %#,\"business_group_id\": %#,\"legal_entity_id\": %#,\"division_id\": %#,\"unit_id\": %#,\"user_id\": %#}]}]",clientSessionId,clientSessionId,[self NSNullToNilForKey:countryId],[self NSNullToNilForKey:businessGroupId],[self NSNullToNilForKey:legalEntityId],[self NSNullToNilForKey:divId],[self NSNullToNilForKey:unitId], [self NSNullToNilForKey:userId]];
But the problem is that, though the if loop is getting invoked. The value returned from the if loop of NSNullToNilForKey is <null> instead of null. How can I sort this out?
You're creating a string from a format, all of the parameters are added by taking their description, what you're seeing is the description of the NSNull instance.
Your method should specifically return a string and you should choose explicitly what string you want to return.
- (id)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return #"NSNull";
}
return number;
}
try this
change the type anyobject id to NSNumber *
- (NSNumber *)NSNullToNilForKey:(NSNumber *)number
{
if ([[number stringValue] length] == 0){
return [NSNull null];
}
return number;
}

Comaparing NSString in Objective C

Any one please help me to understand the String comparison technique in Objective-C
NSString *strNew1 = #"AA";
NSString *strNew2 = #"AA";
So to compare both the strings we could use,
Method 1. if (strNew1 == strNew2) {
NSLog(#"Equal");
}
or
Method 2: if ([strNew1 isEqualToString:strNew2]) {
NSLog(#"Equal");
}
In this condition both of them are success. But am aware that method 1 will get failed at certain other condition. And also I have tried the below conditions(All are success).
NSString *strNew = #"AA";
NSString *strNew1 = #"AA";
NSString *strNew11 = [[NSString alloc] initWithString:strNew1];
NSString *strNew3 = strNew;
NSArray *arr = #[#"AA"];
NSString *strNew4 = [arr objectAtIndex:0];
NSString *strNew5 = [arr objectAtIndex:0];
_test = strNew5;
_test1 = #"AA";
if ([strNew isEqualToString:strNew1]) {
NSLog(#"Equal");
}
if (strNew == strNew3) {
NSLog(#"Equal1");
}
if (strNew == [arr objectAtIndex:0]){
NSLog(#"Equal2");
}
if (strNew == strNew4){
NSLog(#"Equal3");
}
if (strNew5 == strNew4){
NSLog(#"Equal4");
}
if (strNew4 == [arr objectAtIndex:0]){
NSLog(#"Equal5");
}
if (strNew11 == [arr objectAtIndex:0]){
NSLog(#"Equal11");
}
if (self.test == strNew4){
NSLog(#"Equal3");
}
if (self.test == self.test1){
NSLog(#"Equal3");
}
TEST *test = [TEST new]; // Tried with a class with NSString property with value "AA" . (test.strTest value is #"AA")
if (strNew == test.strTest) {
NSLog(#"Equal"); //success
}
I knew most of them are redundant. Am not able to understand the basics behind this. Please anyone give clear explanation on the concept behind this. Thanks.
In the cases you defined the strings created are internally treated as string literals. The runtime will not allocate different memory space to such strings.
Essentially all the strings that contain the same string literal ("AA" in your case) will point to the same memory location. This is done as a part of memory optimization by Apple.
When you change the value of any string (say to "AB") a new address will be allocated to that NSString object and then == will fail.
You need to use below instance method of NSString class.
- (BOOL)isEqualToString:(NSString *)aString;
So, In your case simply follow below:
if ([strNew isEqualToString strNew4]){
NSLog(#"Equal3");
}
By doing (strNew == strNew4),
You are only comparing the addresses of the objects.
The first way compares pointers, while the second way compares objects.
That is, the first way compares if the pointers have the same value. In this case it is likely that they don't, in the second case the objects will be compared. Since they are initialized the same way they could be equal. (Note, it appears that with the UIButton's implementation of isEqual: the result is always false.)
In most cases using == is not what you want. However, what is appropriate depends on your objective.
if (strNew1 == strNew2) //This compared your pointers
{
}
and
if ([strNew1 isEqualToString:strNew2]) //Compares NSString object
{
}
Remember that isEqualToString: comes with a WARNING
[string1 isEqualToString: string2]
will effectively return false is both strings are nil.

iOS 8: handling data returned from iTunes Search API

I am using iTunes Search APIs to return the number of users that have reviewed my current app version. Since I haven't released the app yet, I have to handle the case where the iT search API returns nothing.
Here's the pertinent code:
NSDictionary *iTunesDict = [NSJSONSerialization
JSONObjectWithData:iTunesData options:0 error:&error];
NSArray *resultCount = #[[iTunesDict valueForKey:#"resultCount"]];
NSLog(#"%#", [resultCount objectAtIndex:0]);
if ([resultCount objectAtIndex:0] == 0) {
self.numberOfReviewers = #"0";
} else {
NSArray *reviewers = #[[[iTunesDict valueForKey:#"results"] valueForKey:#"userRatingCountForCurrentVersion"]];
if ([reviewers objectAtIndex:0] == nil) {
self.numberOfReviewers = #"0";
} else {
NSString *howManyReviewed = [[[reviewers objectAtIndex:0] objectAtIndex:0] stringValue];
self.numberOfReviewers = howManyReviewed;
}
My problem centers around the first if statement. Upon inspection, the value of...
[resultCount objectAtIndex:0] is: (__NSCFNumber *)(long)0
does not satisfy the condition in my first if.
What do I need to make a **(__NSCFNumber *)(long)0 **== 0??
It's returning the data as an NSNumber object. Use the compare: comparison function:
if ([resultCount[0] compare:#0] == NSOrderedSame) {
...
}
else {
...
}
What this is doing is comparing the resultCount object to an NSNumber with the value of 0 (you can use the literal #0 to short-hand an NSNumber as I've done above). compare: returns one of three values:
NSOrderedDescending
NSOrderedSame
NSOrderedAscending
This reads from left to right. So if I was to use NSOrderedDescending, this would read logically "is 0 smaller than resultCount" (in descending order from left to right).
For further reading, check out the comparing NSNumber objects documentation.
Alternatively, because you know it's a long, you can use the longValue method on NSNumber:
if ([resultCount longValue] == 0) {
....
}

Check whether the NSArray object at index is of kind NSString Or NSNumber

This is my NSArray :
(
"tag_name",
3,
"mp4_url",
4,
0,
"back_tag",
5,
1,
"part_id",
"related_list",
2
)
I need to put all the numerical values in some another array.
I used the following code to check whether the value fetched from the array was a numeric or a string, but it didn't work. Every time i get the value from an array as NSString.
for (int i=0; i<arr.count; i++) {
id obj=[arr objectAtIndex:i];
if ([obj isKindOfClass:[NSString class]])
{
// It's an NSString, do something with it...
NSLog(#"its string");
}else{
// It's an Numerical value, do something with it...
NSLog(#"its integer value");
}
}
I know that array stores only kind of objects in it, so while fetching i'm getting the value as NSString(i.e object). But is there anyway to check whether the value stored was a numeric value.
Please can anyone help me..
Thanks
You can't just turn an NSString into an NSNumber but there are ways that you can try to get he numeric value out of them.
This is one option but you could also have a look at NSNumberFormatter.
If all of the numbers are integers then you could do something like this...
// always use fast enumeration
for (NSString *string in arr) {
NSInteger integer = [string integerValue];
// have to check explicitly for 0 as a non-numeric would return 0 above
if ([string isEqualToString:#"0"]
|| integer != 0) {
// it is an integer numeric string
} else {
// it is a string
}
}

Simple conditional failing

I have a simple conditional which is failing:
NSNumber *beaconMajor = [NSNumber numberWithInt:33995];
NSNumber *beaconMinor = [NSNumber numberWithInt:59204];
NSNumber *incommingMajor = beacon.major;
NSNumber *incommingMinor = beacon.minor;
NSLog(#"%d", [beaconMajor integerValue]);
NSLog(#"%d", [incommingMajor integerValue]);
NSLog(#"Pre big conditional");
//if the beacon is the one for the test content AND we are very near to it, show that content
if (incommingMinor == beaconMinor) {
NSLog(#"Into big conditional");
if (beacon.proximity == CLProximityImmediate) {
[self performSegueWithIdentifier:#"mainToContent" sender:self];
}
}
I'm grabbing two NSNumbers coming from an iBeacon, and am comparing them to two manually set numbers which I know to correspond. Check the numbers when I log them, they are the same. However the conditional doesn't accept them as being equal so doesn't trigger.
I can't see anything wrong, it's very simple as you can see.
Any thoughts or suggestions?
Thanks.
You are comparing objects (addresses in memory), you need to compare the value of them:
if ([incommingMinor intValue] == [beaconMinor intValue])
You are comparing pointers addresses which will not be equal as beaconMinor and incommingMinor points to a different memory address.
compare the object number value as stated in Antonio's answer (compare the intValue of the instances)
If you are comparing NSNumber use isEqual:
If you are comparing integers then use ==
if ([incommingMinor isEqual: beaconMinor]) {
or
if ([incommingMinor intValue] == [beaconMinor intValue]) {

Resources