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

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

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.

iOS: ActionSheetStringPicker successAction: wrong selection

I am using the ActionSheetStringPicker from the ActionSheetPickers3.0 (since I no longer can use the old picker views because of iOS 8). This is how I am calling the method:
ActionSheetStringPicker *genderPicker = [[ActionSheetStringPicker alloc]
initWithTitle:#"Gender" rows:categoryTypes initialSelection:nil target:self
successAction:#selector(selectedGender:) cancelAction:#selector(cancelledGender)
origin:gender];
[genderPicker showActionSheetPicker];
My success action code is this:
-(void) selectedGender:(NSNumber *)genderSelected {
NSLog(#"selected gender: %#",genderSelected);
if (genderSelected == 0) {
NSLog(#"male");
gender.text = #"Male";
} else {
NSLog(#"female");
gender.text = #"Female";
}
}
I am getting either a 1 or 0 value from the selected gender (male/female) when I NSLog the genderSelected value. My problem is that in my if-statement it always says I picked female. I'm getting the correct value that I select from the picker, but can't seem to figure out what the problem is. Does anyone know how I can get my if-statement working? Thanks!
In your success callback method the parameter you are getting is of type NSNumber. You cannot directly compare the object of type NSNumber with int value 0. Therefore use the following :
if (genderSelected.intValue == 0) {
NSLog(#"male");
gender.text = #"Male";
} else {
NSLog(#"female");
gender.text = #"Female";
}
Well this isn't exactly what I was looking for, but it worked. I set the NSNumber that I was getting as an NSString then compared to a "0" and "1" string. Here is my solution:
-(void) selectedGender:(NSNumber *)genderSelected {
NSString *string = [NSString stringWithFormat:#"%#",genderSelected];
if ([string isEqualToString:#"0"]) {
NSLog(#"male");
} else if ([string isEqualToString:#"1"]) {
NSLog(#"female");
}
}

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) {
....
}

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

iOS - Stanford CS193P Fall 2011 course, Assignment 2 descriptionOfProgram issue

Part of this assignment includes printing out on the display the current equation that is present to be solved, for that I use the following methods:
+ (NSString *)descriptionOfTopOfStack:(NSMutableArray *)stack {
NSMutableString *programFragment = [NSMutableString stringWithString:#""];
id topOfStack = [stack lastObject];
if (topOfStack) [stack removeLastObject];
if ([topOfStack isKindOfClass:[NSNumber class]]) {
[programFragment appendFormat:#"%g", [topOfStack doubleValue]];
} else if ([topOfStack isKindOfClass:[NSString class]]) {
NSString *operation = topOfStack;
if ([self isDoubleOperandOperation:operation]) {
[programFragment appendFormat:#"(%# %# %#)", [self descriptionOfTopOfStack:stack], operation, [self descriptionOfTopOfStack:stack]];
} else if ([self isSingleOperandOperation:operation]) {
[programFragment appendFormat:#"%#( %# )", operation, [self descriptionOfTopOfStack:stack]];
} else if ([ self isNoOperandOperation:operation]) {
[programFragment appendFormat:#"%#", operation];
} else if ([self isVariable:operation]) {
[programFragment appendFormat:#"%#", operation];
}
}
return programFragment;
}
+ (NSString *)descriptionOfProgram:(id)program {
NSMutableArray *stack;
if ([program isKindOfClass:[NSArray class]]) {
stack = [program mutableCopy];
}
return [self descriptionOfTopOfStack:stack];
}
My program computes the results and everything just fine, the only problem is that when I enter a variable, digit or single operand operation the display only shows said last entry, because it doesn't continue to iterate over the rest of the values present in the array, because no other recursive calls are made, any idea how I can make the program execute throughout the entire stack and not have it break the output?
I am not quite sure what you mean. The recursion should stop at a variable, digit or single operand operation. Although for a sin(operand) operation it should continue with the operand.
Did you take into account that your stack might be not completely defined?
Say you enter: 3 Enter 5 + 6 Enter 7 * 9 sqrt
this should translate to: 3+5, 6, sqrt(7*9)
So you have three elements still on your stack, but your approach stopped at sqrt(7*9).
You need to add a check at the to see if there is anything left on the stack, and continue if necessary (and add the comma's).
OK, another hint then (to be added at the end):
if ([stack count]) { // did I finish the entire stack?
[programFragment appendFormat:#"%#, %#", [self describeStack:stack], programFragment];
}
Interestingly you have used a NSMutableString, I did it with a NSString and used the class method stringWithFormat. So each time my result is a new string. I do not know if either approach is better.
aleene already answered, but just to clarify. I added the [stack count] check in the method that calls the recursive function.
+ (NSString *)descriptionOfProgram:(id)program {
NSMutableArray *stack;
NSString *strDesc = #"";
if ([program isKindOfClass:[NSArray class]]) {
// Make a consumable, mutable copy:
stack = [program mutableCopy];
}
while (stack.count) {
strDesc = [strDesc stringByAppendingString:[self descriptionOfTopOfStack:stack]];
if (stack.count) {
// More statements still on stack. We will loop again, but first, append comma separator:
strDesc = [strDesc stringByAppendingString:#", "];
}
}
return strDesc;
}

Resources