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