PDA

View Full Version : UIPicker If Statement




sldice
Jan 18, 2011, 09:54 PM
Could someone please head me in the right direction with my issue? Long story short I am working on a financial sort of calculator. UIPicker 1st component is an array of what type of result you are looking for (ie. Tip, Interest Payment, Loan Payment), 2nd component is a loop of interest rates.

I am having trouble saying if [component 1 objectatIndex =equals "Tip"], do this calculation, if [component 1 objecAtIndex = loan payment[, do this calculation. So I need to know which object in component 1 was chosen, and then do a calculation using component 2's interest rate. I just can't seem to get an if statement to work for that.

Thanks in advance,



dejo
Jan 19, 2011, 09:52 AM
You need to take advantage of a delegate method of UIPickerView and base your logic on the values of its parameters.

sldice
Jan 19, 2011, 09:44 PM
If you feel like looking at the delegate method below, I thought this would work. It works if I choose the 1st if statement for row:0 = @"TIP", but it crashes if I choose the other two rows.





- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row inComponent:(NSInteger)component {

if ([resultTypeHeaderArray objectAtIndex:[thePicker selectedRowInComponent:0]] == @"Tip") {

rateSelected = row + 1;
rateSelected = rateSelected / 100;
float tipTotal = [amountTextField.text floatValue] * rateSelected;

resultLabel.text = [NSString stringWithFormat:@"Tip: $%.2f", tipTotal];

}
else if ([resultTypeHeaderArray objectAtIndex:[thePicker selectedRowInComponent:1]] == @"Monthly Interest Payment")
{

rateSelected = row + 1;
rateSelected = rateSelected / 100;
float interestPayment = [amountTextField.text floatValue] * rateSelected / 365 *30;

resultLabel.text = [NSString stringWithFormat:@"Interest Payment: $%.2f", interestPayment];


}
else if ([resultTypeHeaderArray objectAtIndex:[thePicker selectedRowInComponent:2]] == @"Monthly Interest Earned")
{

rateSelected = row + 1;
rateSelected = rateSelected / 100;
float interestEarned = [amountTextField.text floatValue] * rateSelected / 365 *30;

resultLabel.text = [NSString stringWithFormat:@"Interest Payment: $%.2f", interestEarned];

}
}

dejo
Jan 19, 2011, 10:39 PM
First, why are you comparing to hard-coded strings? Do the number and order of the values in the first component change?

Second, comparing to strings using == is not recommended. NSString has an instance method made specifically to do what you want.

Third, and most importantly, you are not even taking advantage of the values of the parameters you're given. I'm pretty sure you'll only need to do a simple comparison to determine which row of the first component was selected.

sldice
Jan 19, 2011, 11:30 PM
Okay, I'll try and figure that out. Thanks for your thoughts.

sldice
Jan 24, 2011, 06:45 PM
I apologize I was not able to figure this question out my self. Is there anyone else out there who could possibly help me with my question?

I have searched everywhere and tried all the possible code I could think of, but I just can't figure out how to do an if statement with 2 components in the didselectrow method.

dejo
Jan 24, 2011, 06:51 PM
I have searched everywhere and tried all the possible code I could think of, but I just can't figure out how to do an if statement with 2 components in the didselectrow method.
Alright, what are your thoughts on the values of these parameters: didSelectRow: (NSInteger)row and inComponent: (NSInteger)component (which you will want to reference via row and component from within the method)? Do you understand their purpose and what values they contain?

sldice
Jan 24, 2011, 07:05 PM
I would say to me I am thinking:

the didSelectRow: parameter is returning an integer to row of what row was selected

the inComponent: parameter is returning an integer to component of which component was selected

So the purpose and values they contain this is what I think is happening:

In my first component the first choice is "Tip". So I would say the integer for the component would return 0, and the row would return 0?

dejo
Jan 24, 2011, 07:07 PM
In my first component the first choice is "Tip". So I would say the integer for the component would return 0, and the row would return 0?
Bingo!

Does that help in thinking about how to code the logic for your if statement?

sldice
Jan 24, 2011, 07:17 PM
Oh wow, I understood something! It does make sense, thanks for spreading the method out, but I guess I just haven't learned enough to make my next step work, because this is what I tell myself I should do:

if (component == 0 && row == 0) {
DO SOMETHING
}

but it doesn't work

dejo
Jan 24, 2011, 07:22 PM
but it doesn't work
Doesn't work how? Please be specific. Any warnings or errors? Is the condition evaluating to true but something within the if block is not working? Or something else? What debugging have you done for this? Have you confirmed that the values of component and row are what you expect them to be? Or perhaps a breakpoint and stepping through the code? Etc.

sldice
Jan 24, 2011, 07:27 PM
No errors or warnings. The picker works fine, and in that method, if I don't have an if statement my calculation works fine. How the row works and knows I want the row to be the 2nd component rate, I have no idea...



rateSelected = row + 1;
rateSelected = rateSelected / 100;
float tipTotal = [amountTextField.text floatValue] * rateSelected;

resultLabel.text = [NSString stringWithFormat:@"Tip: $%.2f", tipTotal];

dejo
Jan 24, 2011, 07:34 PM
No errors or warnings. The picker works fine, and in that method, if I don't have an if statement my calculation works fine.
And when you do have the if statement, what happens then?

sldice
Jan 24, 2011, 07:40 PM
the calculation does nothing when I change the 2nd component (interest rate), but the else part of the statement does work. So to me, the if part is not recognizing what I am doing.

sldice
Jan 24, 2011, 09:31 PM
I think this might help a little in figuring it out. I can get it to calculate if I move out of the first row of the picker (leaving the @"Tip" row), and then go back to it. Once I go back it runs the calculation. It calculated simultaneously when I didn't have the if statement, meaning I could have component 1 on @"Tip", and flick through the interest rates in component 2, and the calculation would work and change as I flicked through component 2.

nickculbertson
Jan 24, 2011, 09:47 PM
I think this might help a little in figuring it out. I can get it to calculate if I move out of the first row of the picker (leaving the @"Tip" row), and then go back to it. Once I go back it runs the calculation. It calculated simultaneously when I didn't have the if statement, meaning I could have component 1 on @"Tip", and flick through the interest rates in component 2, and the calculation would work and change as I flicked through component 2.

In that case, set the first component you want to start with in the viewDidLoad method.

sldice
Jan 25, 2011, 09:15 AM
Thanks, but I don't think that will solve it. Reason being the label updated immediately with my calculation when I didn't have an if statement and I flicked through the component 2 interest rates. The plan is to have multiple if statements with different calculations depending on the choice in component one. So somehow it is not recognizing the chosen row in component 1 anymore unless I actually click on it or switch rows and come back. Are you saying setting it in viewDidLoad would solve that, or just set component 1 to a certain row?

dejo
Jan 25, 2011, 09:43 AM
Yeah, pickerView:didSelectRow:inComponent: is only called when, as the documentation says, "the user selects a row in a component". So, if they haven't changed anything in the first component, that delegate method won't get triggered with a component value of 0.

Since this is the case, your logic needs to be a little special in how it handles things, since it is reacting to only changes. It should probably incorporate usage of UIPickerView's selectedRowInComponent: instance method. I would write the pseudo-code alongs these lines:

NSInteger comp1row = [thePickerView selectedRowInComponent:0];
NSInteger comp2row = [thePickerView selectedRowInComponent:1];
if (comp1row == 0) { // "Tip" selected
// Calculate a tip based on comp2row
...
}
else if (comp1row = 1) { // "Interest" selected
// Calculate interest based on comp2row
...
}


My apologies for leading you somewhat astray earlier with the request to use the component and row parameters. Not really useful in your case.

sldice
Jan 25, 2011, 10:43 PM
I tried the following method but it gets a warning for non-void function. Guessing I'm typing the method wrong.



- (NSInteger)selectedRowInComponent:(NSInteger)component
{

NSInteger comp1row = [thePicker selectedRowInComponent:0];
NSInteger comp2row = [thePicker selectedRowInComponent:1];

if (comp1row == 0)

{

rateSelected = comp2row+1;
rateSelected = rateSelected / 100;
tipTotal = [amountTextField.text floatValue] * rateSelected;
resultLabel.text = [NSString stringWithFormat:@"Tip: $%.2f", tipTotal];

}


}

cnstoll
Jan 25, 2011, 10:57 PM
You're getting that error because you're supposed to return something of type NSInteger because that's the return type of the method you're implementing...

Typically the structure would go something like this.

1) Decide somewhere that it would be good to know the selectedRowIn"a"Component
2) Declare a variable that you want to put the result in
3) Call the method selectedRowInComponent and store the result in the variable.
4) Do something with the variable (like set a label)

You're trying to do it all in that method, instead of breaking it down into pieces. Instead, try to return the tip you calculate to the caller, and set the label after calling the method by using the return value of selectedRowInComponent.

nickculbertson
Jan 25, 2011, 11:43 PM
If you already got it to work when you select a row, all you need to do is tell the picker where to start. the initial value. I would think all you need is something like this in your viewDidLoad

[resultTypeHeaderArray objectAtIndex:[thePicker selectedRowInComponent:0]] = @"Tip";

or maybe...

[self.picker selectRow:0 inComponent:0];

could be...

[pickerView selectedRowInComponent:0];

It may look like you have "Tips" selected when you load the view but really nothing has been selected yet.

dejo
Jan 26, 2011, 09:53 AM
I tried the following method but it gets a warning for non-void function. Guessing I'm typing the method wrong.
No, you're overriding the wrong method. Calling selectedRowInComponent: from within selectedRowInComponent: will probably result in infinite recursion. As cnstoll lays out, you want to call selectedRowInComponent: from "somewhere that it would be good to know the selectedRowIn"a"Component". One place I can think of would be when "the user selects a row in a component". That place better sound familiar. :)

sldice
Jan 26, 2011, 08:05 PM
Thanks for all the ideas, it really helped. I pretty much got everything working correctly. I'm guessing it's not exactly what you had in mind but it worked! Without changing anything in component1, if I type the amount in the textfield, and then flick through the component2 interest rates, the label updates immediately. I also got the else if statement working where if I choose component1 row:1, it calculates the 2nd calculation. The only issues I am having now, is it does not calculate until I flick through component2 interest rates. Meaning if I open the app and type in the amount, it does not calculate until I change the interest rate. So I guess anytime I update the textfield, it does update the label until I change the row. But with all your help it has helped me 100% and I should be able to hopefully figure the rest out. (I did say hopefully). Here are the 2 methods if anyone has been following.



- (void)pickerView:(UIPickerView *)thePickerView didSelectRow:(NSInteger)row
inComponent:(NSInteger)component {

if ([thePicker selectedRowInComponent:0] == 0) {

rateSelected = [thePicker selectedRowInComponent:1]+1;
rateSelected = rateSelected / 100;
resultTotal = [amountTextField.text floatValue] * rateSelected;
resultLabel.text = [NSString stringWithFormat:@"Tip: $%.2f", resultTotal];

}
else if ([thePicker selectedRowInComponent:0] == 1) {

rateSelected = [thePicker selectedRowInComponent:1]+1;
rateSelected = rateSelected / 100;
resultTotal = [amountTextField.text floatValue] * rateSelected/365*30;
resultLabel.text = [NSString stringWithFormat:@"Interest: $%.2f", resultTotal];


}
}

- (NSInteger)selectedRowInComponent:(NSInteger)component
{

return [thePicker selectedRowInComponent:0];
return [thePicker selectedRowInComponent:1];


}

dejo
Jan 27, 2011, 12:56 AM
So I guess anytime I update the textfield, it does update the label until I change the row.
I assume you mean "it doesn't update the label". There's a solution for this too: UITextField has delegate methods that you can take advantage of and have that code also trigger the calculation, label setting, etc. That is why it is probably best to fork that processing off into its own method that can be called from multiple places.