Simple conditional failing - ios

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]) {

Related

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.

Code runs fine on iPhone 5s+, not previous versions?

When I run this bit of code on an iPhone 5s or higher, it executes as expected. But when I run it on any version lower than a 5s (5, 4s, 4), it does not.
It is supposed to go into the first if statement, ignore the second if statement and execute the else. This works fine in any version over 5s in the simulator, but when I run it on a 5 or 4 it goes into the second if statement... instead of ignoring it and executing the else.
currentProduct.productID is an NSNumber
anything that could help me out would be very appreciated!
NSNumber *currentProductID = [[NSNumber alloc] initWithInt:4121];
if (productPurchased != YES) {
if (currentProduct.productID != currentProductID) {
[self performSegueWithIdentifier:#"InAppPurchaseViewController" sender:nil];
} else {
[self showActivityView];
[self performSelector:#selector(configureExam) withObject:nil afterDelay:0.1];
}
You can't use != (or ==) to compare two objects.
Change the if to:
if (![currentProduct.productId isEqual:currentProductID]) {
On a side note, use modern syntax to create the number:
NSNumber *currentProductID = #4121;
To compare NSNumber you could use
compare: which returns NSComparisonResult
NSNumber *currentProductID = #4121;
if ([currentProduct.productId compare:currentProductID] != NSOrderedSame) {
}
isEqualToNumber:
NSNumber *currentProductID = #4121;
if (![currentProduct.productId isEqualToNumber:currentProductID]) {
}
intValue and compare it like what you did.
NSNumber *currentProductID = #4121;
if ([currentProduct.productId intValue] != [currentProductID intValue]) {
}
I had the same problem and fixed it by extracting integer values from NSNumbers and then compare them. Like below
if ([currentProduct.productID integerValue] != [currentProductID integerValu]) {

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

NSNumber with IF statement issue

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.

Resources