UIPicker If Statement

Discussion in 'iOS Programming' started by sldice, Jan 18, 2011.

  1. macrumors newbie

    Joined:
    Oct 24, 2010
    #1
    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,
     
  2. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #2
    You need to take advantage of a delegate method of UIPickerView and base your logic on the values of its parameters.
     
  3. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #3
    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.



    Code:
    
    - (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]; 
    		
    	}
    }
    
    
     
  4. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #4
    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.
     
  5. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #5
    Okay, I'll try and figure that out. Thanks for your thoughts.
     
  6. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #6
    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.
     
  7. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #7
    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?
     
  8. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #8
    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?
     
  9. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #9
    Bingo!

    Does that help in thinking about how to code the logic for your if statement?
     
  10. sldice, Jan 24, 2011
    Last edited by a moderator: Jan 24, 2011

    thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #10
    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:

    Code:
    if (component == 0 && row == 0) {
    DO SOMETHING
    }
    
    but it doesn't work
     
  11. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #11
    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.
     
  12. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #12
    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...

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

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #13
    And when you do have the if statement, what happens then?
     
  14. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #14
    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.
     
  15. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #15
    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.
     
  16. macrumors regular

    nickculbertson

    Joined:
    Nov 19, 2010
    Location:
    Nashville, TN
    #16
    In that case, set the first component you want to start with in the viewDidLoad method.
     
  17. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #17
    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?
     
  18. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #18
    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:
    Code:
    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.
     
  19. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #19
    I tried the following method but it gets a warning for non-void function. Guessing I'm typing the method wrong.

    Code:
    
    - (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]; 
    		
    	}
    	
    
    }
    
    
     
  20. macrumors 6502

    Joined:
    Aug 29, 2010
    #20
    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.
     
  21. macrumors regular

    nickculbertson

    Joined:
    Nov 19, 2010
    Location:
    Nashville, TN
    #21
    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

    Code:
    [resultTypeHeaderArray objectAtIndex:[thePicker selectedRowInComponent:0]] = @"Tip";
    or maybe...

    Code:
    [self.picker selectRow:0 inComponent:0];
    could be...

    Code:
    [pickerView selectedRowInComponent:0];
    It may look like you have "Tips" selected when you load the view but really nothing has been selected yet.
     
  22. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #22
    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. :)
     
  23. thread starter macrumors newbie

    Joined:
    Oct 24, 2010
    #23
    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.

    Code:
    
    - (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];
    		
    
    	}
    
    
     
  24. Moderator

    dejo

    Staff Member

    Joined:
    Sep 2, 2004
    Location:
    The Centennial State
    #24
    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.
     

Share This Page