UITextView in UITableView becomeFirstResponder returns NO after assignement statement

Discussion in 'iOS Programming' started by terryah, Feb 20, 2013.

  1. terryah, Feb 20, 2013
    Last edited by a moderator: Feb 20, 2013

    macrumors newbie

    Joined:
    Feb 20, 2013
    #1
    Hi Everyone,

    I am having a problem that I cannot seem to fix. I have been looking all over the internet to find a solution but cannot find one.

    I have a UITableView that I am using as data editor. In each cell I have 3 UITextFields and when you click on the Next/Previous buttons I would like it to scroll through the UITextFields and if you are pressing Next from the last UITextField in the cell the focus should move to the next cell.

    All of this works fine if I do it just that way. The problem is that my UITableView is not completely displayed on the screen so if you click Next to a cell that is not on the screen then click Previous to the original cell, any changes you made are lost.

    I therefore added code to the textFieldDidEndEditing function to copy the data to the data element in the NSArray. Now my data is not lost when the above takes place. The problem with this is now my Next/Previous function does not work as the UITextField is no longer able to become first responder.

    I have run some tests and it comes down to having an assignment statement in either the same block with the resignFirstResponder and becomeFirstResponder code or in the textFieldDidEndEditing function. Below is the working and non working code.

    I am really hoping someone can help me with this.

    Working Code
    Code:
    - (void) nextField:(id)sender
    {
        NSLog(@"Next Field");
        UITableViewCell *cellTmp = [[self tableView] cellForRowAtIndexPath:self.selectedIndexPath];
        GradingSchemeCell1 *cell = (GradingSchemeCell1 *)cellTmp;
        GradingScheme *selectedObject = [self.fetchedResultsController objectAtIndexPath:cell.indexPath];
        NSLog(@"Letter Grade: %@, GPA: %@",[selectedObject letterGrade], cell.cellField1.text);
    
        int selectedSection = self.selectedIndexPath.section;
    
        if (cell == nil)
        {
            return;
        }
        if ([cell.cellField1 isFirstResponder])
        {
            [cell.cellField1 resignFirstResponder];
            [cell.minGrade becomeFirstResponder];
            [self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
        }
       ...
    }
    
    Broken Code:
    Code:
    - (void) nextField:(id)sender
    {
        NSLog(@"Next Field");
        UITableViewCell *cellTmp = [[self tableView] cellForRowAtIndexPath:self.selectedIndexPath];
        GradingSchemeCell1 *cell = (GradingSchemeCell1 *)cellTmp;
        GradingScheme *selectedObject = [self.fetchedResultsController objectAtIndexPath:cell.indexPath];
        NSLog(@"Letter Grade: %@, GPA: %@",[selectedObject letterGrade], cell.cellField1.text);
    
        int selectedSection = self.selectedIndexPath.section;
    
        if (cell == nil)
        {
            return;
        }
        if ([cell.cellField1 isFirstResponder])
        {
            [cell.cellField1 resignFirstResponder];
            [COLOR="Red"]selectedObject.gPA = [[NSDecimalNumber alloc] initWithString:cell.cellField1.text];[/COLOR]
            [cell.minGrade becomeFirstResponder];
            [self.tableView scrollToRowAtIndexPath:[self.tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionMiddle animated:YES];
        }
       ...
    }
    
    As you can see above. The only code that is different is the assignment statement after the resignFirstResponder.

    Any help is very appreciated.

    Thanks and Regards,
    Terry
     
  2. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #2
    I usually save the text on every keystroke in my data model when working with textFields in table views.

    Do you have any of the "should" delegate methods implemented and do they return NO in any cases?
     
  3. thread starter macrumors newbie

    Joined:
    Feb 20, 2013
    #3
    Thanks for the reply.

    The only "should" delegate method I use is the textFieldShouldBeginEditing and that one is setup to always return true.

    What delegate do you use to save on each keystroke?

    Regards,
    Terry
     
  4. macrumors 68030

    PhoneyDeveloper

    Joined:
    Sep 2, 2008
    #4
    UITextField is a UIControl subclass and it sends an action message for UIControlEventValueChanged. You just have to register for that message either in IB or code. It also posts a UITextFieldTextDidChangeNotification and your code can register for that notification.
     
  5. thread starter macrumors newbie

    Joined:
    Feb 20, 2013
    #5
    Hi,

    I finally figure out what the problem with my code was. For the UITableViewController I use CoreDataTableViewController as my parent class. In that class is the following function:
    Code:
    - (void)controller:(NSFetchedResultsController *)controller
       didChangeObject:(id)anObject
    	   atIndexPath:(NSIndexPath *)indexPath
    	 forChangeType:(NSFetchedResultsChangeType)type
    	  newIndexPath:(NSIndexPath *)newIndexPath
    {		
        if (!self.suspendAutomaticTrackingOfChangesInManagedObjectContext)
        {
            switch(type)
            {
                case NSFetchedResultsChangeInsert:
                    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                    break;
                    
                case NSFetchedResultsChangeDelete:
                    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    break;
                    
                case NSFetchedResultsChangeUpdate:
                    [self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    break;
                    
                case NSFetchedResultsChangeMove:
                    [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                    [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
                    break;
            }
        }
    }
    
    The assignment statement I use was updating the data in the FetchedResultsController this function was called in order to ensure the TableView was refreshed with the changed data, which was causing the problem I was having. As soon as I commented out the above function everything started working perfectly.

    Thanks,
    Terry
     

Share This Page