Search code examples
iosuitableviewuitextfieldnsmutabledictionary

Trying to disable a button when not all UITextFields are populated in iOS


I am working on an application where I have a UITableView that is made up of custom UITableViewCell's. Each UITableViewCell has a UITextField. What I am trying to do is enable a UIButton when all of the UITextFields are populated, which I am now able to do. My challenge now is to disable this very button when not all of the UITextFields are populated. Here is the code that I am working with:

- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string {

    for (int i = 0; i < [self.table numberOfSections]; i++) {

        NSInteger rows =  [self.table numberOfRowsInSection:i];

        for (int row = 0; row < rows; row++) {

            NSIndexPath *indexPath = [NSIndexPath indexPathForRow:row inSection:i];
            SimpleTableCell *cell = (SimpleTableCell *)[self.table cellForRowAtIndexPath:indexPath];

            NSNumber *numKey = [NSNumber numberWithInt: cell.dataField.tag];
            NSString *text = cell.dataField.text;

            if ([[cell dataField] text] != nil && [[[cell dataField] text] length] > 0) {

                [_dict setObject:text forKey:numKey];

                NSArray *keys = [_dict allKeys];

                if ([keys count] == ([_dataName count] - 1)) { //where _dataName is the array that is populating my UITableView

                    [_doneButton setEnabled:YES];
                    [_doneButton.titleLabel setFont:[UIFont boldSystemFontOfSize:28]];

                }

            } else { //if there is a UITextField that is empty

                [_dict removeObjectForKey:numKey];

                NSArray *keys = [_dict allKeys];
                //below is the clause where I disable the button, after checking if there is a single UITextField that is not populated
                if ([keys count] < ([_tireName count] - 1)) {

                    [_doneButton setEnabled:NO];
                    [_doneButton.titleLabel setFont:[UIFont systemFontOfSize:28]];

                }

            }

        }

    }

    return YES;
}

It is able to enable the button only when all of the fields are populated, which is precisely what I want, but unfortunately, it only disables the button when there are three empty UITextFields. My approach in doing this is:

As I go through each UITextField in the UITableView, I check to see if the UITextField is empty, or not. If it is not empty, I enter the string value from the UITextField into an NSMutableDictionary using the UITextFields tag value as the key. If the UITextField is empty, then I simply remove the object connected to that key. In theory, my approach makes sense, but it is not working as I hoped. Can anyone see what I am doing wrong?


Solution

  • when textField:shouldChangeCharactersInRange:replacementString: gets called, the textField's text value has not yet been changed. This method is used to determine if the text entered by the user should be allowed, before the text actually changes. So when you're checking to see if the text is empty, the text field that is being edited will say it is not empty even though it is about to become empty.

    in other words, if you are editing a text field that has "A" inside of it, and the user presses a backspace, when you check the text in this method, it will say that it is "A", not that it is "". So when you clear the text of one of your text fields, this will never disable the button.

    When removing text from a second text field, it should catch the change to the previous text field, however you are disabling the button if ([keys count] < ([_tireName count] - 1)) I'm fairly certain that this should be if([keys count] < [_tireName count]) likewise i think you also want if([keys count] == [_dataName count]) unless you actually expect for _dataName and _tireName to always have 1 more record than your dictionary.

    because you are disabling the button when you have less than [_tireName count] -1 keys in your dictionary, it appears that you are never going to disable the button unless you have 2 empty text fields.

    Once you clear the second text field, as soon as you edit a third, it will think it's time for you to finally disable the button.

    you could try changing

     NSString *text = cell.dataField.text;
    

    to something more like this

    NSString* text;
    if(textfield == cell.dataField) //if this cell's textfield is the field we are editing
    {
        text = [cell.dataField.text stringByReplacingCharactersInRange:range withString:string];
    }
    else
    {
        text = cell.dataField.text;
    }
    

    This will prevent you from looking at the old value of the textfield you are editing when doing the validation. And change if([keys count] < (_tireName count] -1)) to if([keys count] < [_tireName count]).

    There's probably also a way you could change it so that you don't need to loop through all the rows in your tableview, but if you only have 8 rows in your tableview, that kind of a change would be very little gain.