UIButtons not enabling other buttons

Through the awesome help of people on this board I am almost done my app for my students! I was able to make a toolbar appear over the keyboard that has a previous and next buttons. I then made the buttons go between three input fields.

If the user starts in the first field they can go back and forth between all the fields, just like I thought you would if they use the prev/next buttons. However, if the user was on text field three and then clicks on the first field, the buttons stay as they were and then don't work right.

-(void)keyboardWillShow:(id)sender{
    if ([inputA isFirstResponder]) {
        [nextButton setEnabled:YES];
        [previousButton setEnabled:NO];
    } else if ([inputB isFirstResponder]) {
        [nextButton setEnabled:YES];
        [previousButton setEnabled:YES];
    } else if ([inputC isFirstResponder]) {
        [nextButton setEnabled:NO];
        [previousButton setEnabled:YES];
    }
}

... cycles through the next text fields

-(void)nextField:(id)sender{
    if ([inputA isFirstResponder]) {
        [inputB becomeFirstResponder];
        [previousButton setEnabled:YES];
        [nextButton setEnabled:YES];
    } else if ([inputB isFirstResponder]) {
        [inputC becomeFirstResponder];
        [previousButton setEnabled:YES];
        [nextButton setEnabled:NO];
    } else if ([inputC isFirstResponder]) {
        [inputB becomeFirstResponder];
        [previousButton setEnabled:YES];
        [nextButton setEnabled:YES];
    }
}

... cycles through previous text fields

-(void)previousField:(id)sender{
    if ([inputC isFirstResponder]) {
        [inputB becomeFirstResponder];
        [nextButton setEnabled:YES];
        [previousButton setEnabled:YES];
    } else if ([inputB isFirstResponder]) {
        [inputA becomeFirstResponder];
        [nextButton setEnabled:YES];
        [previousButton setEnabled:NO];
    } else if ([inputA isFirstResponder]) {
        [inputB becomeFirstResponder];
        [nextButton setEnabled:YES];
        [previousButton setEnabled:YES];
    }
}

In my keyboard code, the previous button calls previousField, and the next button calls nextField. I figured that when I did the keyboardWillShow, I was setting the different inputs as first responder, but that is only on the first run through.

Is there a way to make it so when the user clicks on the field it becomes the first responder?

Answers


Two things I can suggest: first, do it DRY: "Don't Repeat Yourself". Anytime you see the same code over and over, move it to a method. Secondly you didn't specify who calls keyboardWillShow. Check in your nib that it is being called by each inputX upon EditingDidBegin. So the shorter code would be:

-(void) setPrevNextButtons {  //ensures that Prev/Next buttons are correct for current firstResponder
    if ([inputA isFirstResponder]) {
        [nextButton setEnabled:YES];
        [previousButton setEnabled:NO];
    } else if ([inputB isFirstResponder]) {
        [nextButton setEnabled:YES];
        [previousButton setEnabled:YES];
    } else if ([inputC isFirstResponder]) {
        [nextButton setEnabled:NO];
        [previousButton setEnabled:YES];
    }
}

-(void)keyboardWillShow:(id)sender{
    [self setPrevNextButtons];
}

//goes through the different text fields
-(void)nextField:(id)sender{

    if ([inputA isFirstResponder]) {
        [inputB becomeFirstResponder];
    }else if ([inputB isFirstResponder]) {
        [inputC becomeFirstResponder];
    }    
    [self setPrevNextButtons];
}

-(void)previousField:(id)sender{
    if ([inputC isFirstResponder]) {
        [inputB becomeFirstResponder];
    } else if ([inputB isFirstResponder]) {
        [inputA becomeFirstResponder];
    }
    [self setPrevNextButtons];

}

If you felt like being tricky, you could also do this:

-(void) setPrevNextButtons {
    [previousButton setEnabled: [inputB isFirstResponder] || 
                                [inputC isFirstResponder]  ];
    [nextButton setEnabled: [inputA isFirstResponder] || 
                            [inputB isFirstResponder]  ];
}

As for triggering the updating, UITextField has a delegate method -textFieldDidBeginEditing:, which you could use to call -setPrevNextButtons as proposed by @mackworth. Several other methods exist that do similar things—see the related delegate protocol for more information.

For instance, try this controlling code in the text field's delegate:

- (void)textFieldDidBeginEditing:(UITextField *)textField {
    if (textField == inputA || textField == inputB || textField == inputC)
        [self setPrevNextButtons];
}

It should go without saying that you'll have to set the delegate for the text fields for this to work.


Need Your Help

Web audio API equalizer

javascript filter web-audio equalizer

I have been looking around for creating an audio equalizer using the Web audio API: http://webaudio.github.io/web-audio-api/

Using segues for programmatically constructed tableview cells

ios ios5 uitableview uistoryboard uistoryboardsegue

I am avoiding the use of static prototype cells in storyboards mode of interface builder. But I still want to use segues when those cells are pressed to display the detail view controller.