Method to put NSString and NSNumber into array - iphone

It's a calculator. I have a display where I can put digits and variables (x, y etc.). When I push Enter button it sends what is on display to array with all operand.
As on display can be NSString (variables) or NSNumber (digits) I thought to use "id" as method argument.
- (IBAction)enterPressed
{
[self.brain pushOperand:self.display.text];
}
/////////////////////
- (void) pushOperand:(id)operand
{
////// So if operand is digit I need to transform it into NSNumber.
NSNumber *digitToStack = [NSNumber numberWithDouble:operand];
/////// Here is problem - "Sending '___strong id' to parameter of incompatible type 'double'
NSNumber *digitToStack = [operand doubleValue];
//////// If i do like this, i have warning - "Initializing 'NSNumber *__strong' with an expression of incompatible type 'double'
[self.programStack addObject:operand];
}
I don't understand what this warnings are all about.
So the question is can I somehow put in Array NSNumber and NSString using id method, or how should I do it?
Can i 'transform' argument from 'id' method into NSNumber?

Yes you can "transform" your argument of operand, but you'd need to do a cast.
Also, the line:
NSNumber *digitToStack = [NSNumber numberWithDouble:operand];
fails because "operand" is an Objective C object while that function is expecting a C-style double type (which is NOT an Objective C object).
Here's some code I wrote off the top of my head:
// Let's make operand always be a NSString object
// since that's what is being passed in from the label
- (void) pushOperand:(NSString *)operand
{
double doubleValueFromOperand = [operand doubleValue];
if(fabs(doubleValueFromOperand) != HUGE_VAL)
{
NSNumber *digitToStack = [NSNumber numberWithDouble:doubleValueFromOperand];
if(doubleValueFromOperand != 0.0)
{
[self.programStack addObject:digitToStack];
return;
} else {
// because NSString's doubleValue also returns 0.0 for a
// non-numerical string, let's make sure the input from the label
// is not 0.0
if([operand compare: #"0.0" options: NSCaseInsensitiveSearch range: NSMakeRange(0, 3)] == NSOrderedSame)
{
// the operand string *is* a 0.0 input, so let's add it to your stack and return
[self.programStack addObject: digitToStack];
return;
}
}
}
// if we get to this point, we probably have a non-numerical string object
[self.programStack addObject: operand];
}
This code hasn't been tested, has no warranties, and could certainly use a further cleaning up and optimization (e.g. the check for "0.0" isn't what I would put into production code, myself).
But hopefully this is enough to get you further along, Sasha!

Related

Condition always fails though the comparative values seems correct in iOS

When I check the value of number in nslog it shows '0'
NSMutableDictionary *data = [[NSMutableDictionary alloc] initWithContentsOfFile: path];
NSNumber *number=[data objectForKey:#"serial"];
NSLog(#"%#",number);
if(number ==0 )
{
imgButton.hidden=YES;
}
But the condition always fails , I also changed the code like this
NSString *number=[data objectForKey:#"serial"]
NSLog(#"%#",number);
if(number == #"0" )
{
imgButton.hidden=YES;
}
But here too the condition fail ,What is the issue with this?
In the first code you are checking a NSNumber, object, against an int.
The correct check is:
if([number intValue] == 0) {
imgButton.hidden = YES;
}
In the second code you are checking two NSString, but you have to use the "isEqualToString" method and not "==". The correct code is:
if([number isEqualToString:#"0"]) {
imgButton.hidden = YES;
}
NSNumber is an object, 0 is an integer (a primitive type). They will never be equal. But you can change the comparison like this [number intValue] == 0 and this will work when the value of your NSNumber is 0.
On the string comparison, you should use the method
isEqualToString:NSString *)string
for the comparison.
For NSNumbers its
isEqualToNumber:(NSNumber *)number
Because otherwise you arent comparing if they have the same value, but if they are stored in identical memory space.

Use return value as argument to method

Is it possible to use the return value of a method as the argument for a different method invocation? I'm using Objective-C.
What I'm going for is something like this:
stringOutput = [object1 method1:[object2 method2:[object3 method3]]];
where method 3 returns a string that goes into method 2, which returns a string that goes into method 1, which returns a string that goes into stringOutput.
Do you mean sending the result from one method as the parameter for another?
NSString *string = [self myMethod:[self myMethod2]];
Where the methods are
- (NSString *)myMethod2 {
return #"A String";
}
- (NSString *)myMethod:(NSString *)string {
// Do something with string
// Return another string
return #"Something else";
}

How to compare a NSNumber in an if

How to:
if (myNSNumber == 1)
{
...
}
This doesn't seem to build
The object:
If myNSNUmber is NSNumber, your code should read,
if ([myNSNumber intValue] == 1) {
...
}
If it is NSInteger, you can directly compare it with an integer literal. Because NSInteger is a primitive data type.
if (myNSNumber == 1) {
...
}
Note: Make sure you don't have * in your declaration. Your NSInteger declarations should read,
NSInteger myNSNUmber; // RIGHT
NSInteger *myNSNUmber; // WRONG, NSInteger is not a struct, but it is a primitive data type.
The following is based on #BoltClock's answer, which he recently posted here
However if you do need to use a pointer to an NSInteger (that is, NSInteger *) for some reason, then you need to dereference the pointer to get the value:
if (*myNSNUmber == 11) {
}
NSInteger is normally a plain int type so your code should work fine.
if myNSNumber a NSNumber object (as variable name suggests) then you should extract its int value:
if ([myNSNumber intValue] == 1)
{
...
}

Why isn't this conditional statement working with NSUserDefault?

I'm having a problem getting one of my conditional statements to display data correctly. Here is the code I'm working with:
NSUserDefaults *pickerDefaults = [NSUserDefaults standardUserDefaults];
NSString *myString = [pickerDefaults stringForKey:#"userpicker"];
NSString *string = #"Name1";
NSLog(#"%#",myString); //This prints out Name1
NSLog(#"%#",string); //This also prints out Name1
if (myString == string) {
[pickerArray addObject:#"Name Other"];
}
else {
return;
}
I can't get this if statement to add that object to the UIPicker eventhough both strings are equal to each other. However, if I change it to not equal to != then it display's the object in the UIPickerView. I don't understand what I'm doing wrong. Any help would be great. Thanks.
To compare string objects, don't use their pointer values, but compare using
[string isEqualToString:myString]
if (myString == string) // Wrong : It compares address of two NSStrings
if ([myString isEqualToString:string]) // This compares values of NSStrings
{
}

Appending string to UILabel text?

I'm starting to develop for the iPhone. I have a beginner-type question, I'm sure:
I have this, which works:
testLabel.text = [NSString stringWithFormat:#"%# to %#", testLabel.text, newLabelText];
I wish I could use the "+=" operator, but I get a compile error (Invalid operands to binary +, have 'struct NSString *' and 'struct NSString *'):
testLabel.text += [NSString stringWithFormat:#"to %#", newLabelText];
Why can't I do this?
Also, how can I shorten my first snippet of code?
You can't use the += operator because C and Objective-C do not allow operator overloading. You're trying to use += with two pointer types, which is not allowed -- if the left-hand side of a += expression has a pointer type, then the right-hand side must be of an integral type, and the result is pointer arithmetic, which is not what you want in this case.
Think about using an NSMutableString - you can use the appendString: method, as in:
NSMutableString *str = [#"hello" mutableCopy];
[str appendString:#" world!"];
That can't be done because ObjectiveC does not support it, ObjectiveC is a small layer over C.
testLabel.text = [testLabel.text stringByAppendingFormat:#" to %#", newLabelText];
NSString are NOT mutable (they can't be changed), that's why you can't use +=.
NSMutableString can be changed. You might be able to use them here.
Your code is already pretty minimal. Objective-C is a expressive language so just get used to long, descriptive function and variable names.
try this:
// usage: label.text += "abc"
public func += (a:inout String?, b:String) {
a = (a ?? "") + b
}
give this custom operator a try:
let label = UILabel()
label.text = "abc"
label.text += "_def"
print(label.text) // “abc_def”