Making a UITableView scroll when text field is selected


Making a UITableView scroll when text field is selected



After a lot of trial and error, I'm giving up and asking the question. I've seen a lot of people with similar problems but can't get all the answers to work right.

I have a UITableView which is composed of custom cells. The cells are made of 5 text fields next to each other (sort of like a grid).

When I try to scroll and edit the cells at the bottom of the UITableView, I can't manage to get my cells properly positioned above the keyboard.

I have seen many answers talking about changing view sizes,etc... but none of them has worked nicely so far.

Could anybody clarify the "right" way to do this with a concrete code example?


Results for performSelector: differ from standard dot notation call?

1:

How to add a breakpoint to objc_exception_throw?
If you use UITableViewController instead of UIViewController, it will automatically did so.. How to specify an beginTime for an animation by using CFTimeInterval?
iPhone web application development [closed]Reload model for UITableViewController before [tableview reloadData]

2:

When should you NOT use the asterisk (*) when declaring a variable in Objective C
The function this does the scrolling could be enough simpler:. iPhone/Android Dev for Pocket Change?
- (void) textFieldDidBeginEditing:(UITextField *)textField {     UITableViewCell *cell;      if (floor(NSFoundationVersionNumber) <= NSFoundationVersionNumber_iOS_6_1) {     // Load resources for iOS 6.1 or earlier         cell = (UITableViewCell *) textField.superview.superview;      } else {         // Load resources for iOS 7 or later         cell = (UITableViewCell *) textField.superview.superview.superview;         // TextField -> UITableVieCellContentView -> (in iOS 7!)ScrollView -> Cell!     }     [tView scrollToRowAtIndexPath:[tView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES]; } 
That's it. Best Security Framework to secure and authenticate an iPhone app which uses REST?No calculations at all..

3:

I'm doing any thing very similar it's generic, no need to compute any thing specific for your code. Just check the remarks on the code:. In MyUIViewController.h.
@interface MyUIViewController: UIViewController <UITableViewDelegate, UITableViewDataSource> {      UITableView *myTableView;      UITextField *actifText; }  @property (nonatomic, retain) IBOutlet UITableView *myTableView; @property (nonatomic, retain) IBOutlet UITextField *actifText;  - (IBAction)textFieldDidBeginEditing:(UITextField *)textField; - (IBAction)textFieldDidEndEditing:(UITextField *)textField;  -(void) keyboardWillHide:(NSNotification *)note; -(void) keyboardWillShow:(NSNotification *)note;  @end 
In MyUIViewController.m.
@implementation MyUIViewController  @synthesize myTableView; @synthesize actifText;  - (void)viewDidLoad  {     // Register notification when the keyboard will be show     [[NSNotificationCenter defaultCenter] addObserver:self                                           selector:@selector(keyboardWillShow:)                                           name:UIKeyboardWillShowNotification                                           object:nil];      // Register notification when the keyboard will be hide     [[NSNotificationCenter defaultCenter] addObserver:self                                           selector:@selector(keyboardWillHide:)                                           name:UIKeyboardWillHideNotification                                           object:nil]; }  // To be link with your TextField event "Editing Did Begin" //  memoryze the current TextField - (IBAction)textFieldDidBeginEditing:(UITextField *)textField {     self.actifText = textField; }  // To be link with your TextField event "Editing Did End" //  release current TextField - (IBAction)textFieldDidEndEditing:(UITextField *)textField {     self.actifText = nil; }  -(void) keyboardWillShow:(NSNotification *)note {     // Get the keyboard size     CGRect keyboardBounds;     [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] receive Value: &keyboardBounds];      // Detect orientation     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];     CGRect frame = self.myTableView.frame;      // Start animation     [UIView beginAnimations:nil context:NULL];     [UIView setAnimationBeginsFromCurrentState:YES];     [UIView setAnimationDuration:0.3f];      // Reduce size of the Table view      if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)         frame.size.height -= keyboardBounds.size.height;     else          frame.size.height -= keyboardBounds.size.width;      // Apply new size of table view     self.myTableView.frame = frame;      // Scroll the table view to see the TextField just above the keyboard     if (self.actifText)       {         CGRect textFieldRect = [self.myTableView convertRect:self.actifText.bounds fromView:self.actifText];         [self.myTableView scrollRectToVisible:textFieldRect animated:NO];       }      [UIView commitAnimations]; }  -(void) keyboardWillHide:(NSNotification *)note {     // Get the keyboard size     CGRect keyboardBounds;     [[note.userInfo valueForKey:UIKeyboardFrameBeginUserInfoKey] receive Value: &keyboardBounds];      // Detect orientation     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];     CGRect frame = self.myTableView.frame;      [UIView beginAnimations:nil context:NULL];     [UIView setAnimationBeginsFromCurrentState:YES];     [UIView setAnimationDuration:0.3f];      // Increase size of the Table view      if (orientation == UIInterfaceOrientationPortrait || orientation == UIInterfaceOrientationPortraitUpsideDown)         frame.size.height += keyboardBounds.size.height;     else          frame.size.height += keyboardBounds.size.width;      // Apply new size of table view     self.myTableView.frame = frame;      [UIView commitAnimations]; }  @end 

Swift 1.2+ version:

class ViewController: UIViewController, UITextFieldDelegate {     @IBOutlet weak var activeText: UITextField!     @IBOutlet weak var tableView: UITableView!      override func viewDidLoad() {         NSNotificationCenter.defaultCenter().addObserver(self,             selector: Selector("keyboardWillShow:"),             name: UIKeyboardWillShowNotification,             object: nil)         NSNotificationCenter.defaultCenter().addObserver(self,             selector: Selector("keyboardWillHide:"),             name: UIKeyboardWillHideNotification,             object: nil)     }      func textFieldDidBeginEditing(textField: UITextField) {         activeText = textField     }      func textFieldDidEndEditing(textField: UITextField) {         activeText = nil     }      func keyboardWillShow(note: NSNotification) {         if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {             var frame = tableView.frame             UIView.beginAnimations(nil, context: nil)             UIView.setAnimationBeginsFromCurrentState(true)             UIView.setAnimationDuration(0.3)             frame.size.height -= keyboardSize.height             tableView.frame = frame             if activeText != nil {                 let rect = tableView.convertRect(activeText.bounds, fromView: activeText)                 tableView.scrollRectToVisible(rect, animated: false)             }             UIView.commitAnimations()         }     }      func keyboardWillHide(note: NSNotification) {         if let keyboardSize = (note.userInfo?[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.CGRectValue() {             var frame = tableView.frame             UIView.beginAnimations(nil, context: nil)             UIView.setAnimationBeginsFromCurrentState(true)             UIView.setAnimationDuration(0.3)             frame.size.height += keyboardSize.height             tableView.frame = frame             UIView.commitAnimations()         }     } } 

4:

I think I've come up with the quick fix to match the behaviour of Apple's apps.. First, in your viewWillAppear: subscribe to the keyboard notifications, so you know when the keyboard will show and hide, and the system will tell you the size of the keyboard, although dont' forreceive to unregister in your viewWillDisappear:..
[[NSNotificationCenter defaultCenter]     addObserver:self        selector:@selector(keyboardWillShow:)            name:UIKeyboardWillShowNotification          object:nil]; [[NSNotificationCenter defaultCenter]     addObserver:self        selector:@selector(keyboardWillHide:)            name:UIKeyboardWillHideNotification          object:nil]; 
Implement the methods similar to the below so this you adjust the size of your tableView to match the visible area once the keyboard shows. Here I'm tracking the state of the keyboard separately so I must choose when to set the tableView back to full height myself, since you receive these notifications on every field change. Don't forreceive to implement keyboardWillHide: and choose any where appropriate to fix your tableView size..
-(void) keyboardWillShow:(NSNotification *)note {     CGRect keyboardBounds;     [[note.userInfo valueForKey:UIKeyboardBoundsUserInfoKey] receive Value: &keyboardBounds];     keyboardHeight = keyboardBounds.size.height;     if (keyboardIsShowing == NO)     {         keyboardIsShowing = YES;         CGRect frame = self.view.frame;         frame.size.height -= keyboardHeight;          [UIView beginAnimations:nil context:NULL];         [UIView setAnimationBeginsFromCurrentState:YES];         [UIView setAnimationDuration:0.3f];         self.view.frame = frame;         [UIView commitAnimations];     } } 
Now here's the scrolling bit, i job out a few sizes first, then i see where i are in the visible area, and set the rect i want to scroll to to be either the half view above or below the middle of the text field based on where it is in the view. In this case, i have an array of UITextFields and an enum this keeps track of them, so multiplying the rowHeight by the row number gives us the actual offset of the frame within this outer view..
- (void) textFieldDidBeginEditing:(UITextField *)textField {     CGRect frame = textField.frame;     CGFloat rowHeight = self.tableView.rowHeight;     if (textField == textFields[CELL_FIELD_ONE])     {         frame.origin.y += rowHeight * CELL_FIELD_ONE;     }     else if (textField == textFields[CELL_FIELD_TWO])     {         frame.origin.y += rowHeight * CELL_FIELD_TWO;     }     else if (textField == textFields[CELL_FIELD_THREE])     {         frame.origin.y += rowHeight * CELL_FIELD_THREE;     }     else if (textField == textFields[CELL_FIELD_FOUR])     {         frame.origin.y += rowHeight * CELL_FIELD_FOUR;     }     CGFloat viewHeight = self.tableView.frame.size.height;     CGFloat halfHeight = viewHeight / 2;     CGFloat midpoint = frame.origin.y + (textField.frame.size.height / 2);     if (midpoint < halfHeight)     {         frame.origin.y = 0;         frame.size.height = midpoint;     }     else     {         frame.origin.y = midpoint;         frame.size.height = midpoint;     }     [self.tableView scrollRectToVisible:frame animated:YES]; } 
This seems to job quite nicely..

5:

I had the same problem although noticed this it appears only in one view. So I began to look for the differences in the controllers.. I found out this the scrolling behavior is set in - (void)viewWillAppear:(BOOL)animated of the super instance.. So be sure to implement like this:.
- (void)viewWillAppear:(BOOL)animated {     [super viewWillAppear:animated];     // your code } 
And it doesn't matter if you use UIViewController or UITableViewController; checked it by putting a UITableView as a subview of self.view in the UIViewController. It was the same behavior. The view didn't allow to scroll if the call [super viewWillAppear:animated]; was missing..

6:

If you must use UITableViewController, you receive the functionality for free. Sometimes, however, this is not an option, specifically if you need multiple views not just the UITableView.. Some of the solutions presented here don't job on iOS ≥4, any don't job on iPad or in landscape mode, any don't job for Bluetooth keyboards (where i don't want any scrolling), any don't job when switching between multiple text fields. So if you choose any solution, make sure to test these cases. This is the quick fix i use used in InAppSettingsKit:.
- (void)_keyboardWillShow:(NSNotification*)notification {     if (self.navigationController.topViewController == self) {         NSDictionary* userInfo = [notification userInfo];          // i don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0         NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];         if (!keyboardFrameValue) {             keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];         }          // Reduce the tableView height by the part of the keyboard this actually covers the tableView         CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;         if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {             windowRect = IASKCGRectSwap(windowRect);         }         CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];         if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {             viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);         }         CGRect frame = _tableView.frame;         frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);          [UIView beginAnimations:nil context:NULL];         [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];         [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];         _tableView.frame = frame;         [UIView commitAnimations];          UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;         NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];          // iOS 3 sends hide and show notifications right after each another         // when switching between textFields, so cancel -scrollToOldPosition requests         [NSObject cancelPreviousPerformRequestsWithTarreceive :self];          [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];     } }  - (void) scrollToOldPosition {   [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES]; }  - (void)_keyboardWillHide:(NSNotification*)notification {     if (self.navigationController.topViewController == self) {         NSDictionary* userInfo = [notification userInfo];          [UIView beginAnimations:nil context:NULL];         [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];         [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];         _tableView.frame = self.view.bounds;         [UIView commitAnimations];          [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];     } }    
Here's the full code of the class in InAppSettingsKit. To test it, use the "Complete List" child pane where you must test the scenarios mentioned above..

7:

i may have missed this, as i didn't read the whole post here, although what i came up with seems deceptively simple. i haven't put this through the wringer, testing in all situations, although it seems like it should job just fine.. simply adjust the contentInset of the tableview by the height of the keyboard, and then scroll the cell to the bottom:.
- (void)keyboardWasShown:(NSNotification *)aNotification {     NSDictionary* info = [aNotification userInfo];     CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;      UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);     self.myTableView.contentInset = contentInsets;     self.myTableView.scrollIndicatorInsets = contentInsets;      [self.myTableView scrollToRowAtIndexPath:self.currentField.indexPath atScrollPosition:UITableViewScrollPositionBottom animated:YES]; } 
and of course.
- (void)keyboardWasHidden:(NSNotification *)aNotification {     [UIView animateWithDuration:.3 animations:^(void)      {         self.myTableView.contentInset = UIEdgeInsetsZero;         self.myTableView.scrollIndicatorInsets = UIEdgeInsetsZero;     }]; } 
is this too simple? am i missing any thing? so far it is working for me fine, although as i said, i haven't put it through the wringer....

8:

The simplest quick fix for Swift:.
override func viewDidLoad() {     super.viewDidLoad()      searchBar?.becomeFirstResponder()     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillShow(_:)), name: UIKeyboardDidShowNotification, object: nil)     NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(MyViewController.keyboardWillHide(_:)), name: UIKeyboardDidHideNotification, object: nil) }  deinit {     NSNotificationCenter.defaultCenter().removeObserver(self) }  func keyboardWillShow(notification: NSNotification) {     if let userInfo = notification.userInfo {         if let keyboardHeight = userInfo[UIKeyboardFrameEndUserInfoKey]?.CGRectValue.size.height {             tableView.contentInset = UIEdgeInsetsMake(0, 0, keyboardHeight, 0)         }     } }  func keyboardWillHide(notification: NSNotification) {     UIView.animateWithDuration(0.2, animations: { self.table_create_issue.contentInset = UIEdgeInsetsMake(0, 0, 0, 0) })     // For any  reason adding inset in keyboardWillShow is animated by itself although  removing is not, that's why i have to use animateWithDuration here     } 

9:

Combining and filling in the blanks from several answers (in particular Ortwin Gentz, user 98013) and ananother post, this will job out of the box for SDK 4.3 on an iPad in Portrait or Landscape mode: .
@implementation UIView (FindFirstResponder) - (UIResponder *)findFirstResponder {   if (self.isFirstResponder) {             return self;        }    for (UIView *subView in self.subviews) {     UIResponder *firstResponder = [subView findFirstResponder];     if (firstResponder != nil) {       return firstResponder;     }   }    return nil; } @end  @implementation MyViewController  - (UIResponder *)currentFirstResponder {   return [self.view findFirstResponder]; }  - (IBAction)editingEnded:sender {   [sender resignFirstResponder]; }  - (BOOL)textFieldShouldReturn:(UITextField *)textField {   [textField resignFirstResponder];   return NO; }  - (void)textFieldDidBeginEditing:(UITextField *)textField {   UITableViewCell *cell = (UITableViewCell*) [[textField superview] superview];   [_tableView scrollToRowAtIndexPath:[_tableView indexPathForCell:cell] atScrollPosition:UITableViewScrollPositionTop animated:YES]; }  - (void)keyboardWillShow:(NSNotification*)notification {   if ([self currentFirstResponder] != nil) {     NSDictionary* userInfo = [notification userInfo];      // i don't use SDK constants here to be universally compatible with all SDKs ≥ 3.0     NSValue* keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardBoundsUserInfoKey"];     if (!keyboardFrameValue) {       keyboardFrameValue = [userInfo objectForKey:@"UIKeyboardFrameEndUserInfoKey"];     }      // Reduce the tableView height by the part of the keyboard this actually covers the tableView     CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;     CGRect viewRectAbsolute = [_tableView convertRect:_tableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];     CGRect frame = _tableView.frame;     if (UIInterfaceOrientationLandscapeLeft == self.interfaceOrientation ||UIInterfaceOrientationLandscapeRight == self.interfaceOrientation ) {       windowRect = CGRectMake(windowRect.origin.y, windowRect.origin.x, windowRect.size.height, windowRect.size.width);       viewRectAbsolute = CGRectMake(viewRectAbsolute.origin.y, viewRectAbsolute.origin.x, viewRectAbsolute.size.height, viewRectAbsolute.size.width);     }     frame.size.height -= [keyboardFrameValue CGRectValue].size.height - CGRectGetMaxY(windowRect) + CGRectGetMaxY(viewRectAbsolute);      [UIView beginAnimations:nil context:NULL];     [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];     [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];     _tableView.frame = frame;     [UIView commitAnimations];      UITableViewCell *textFieldCell = (id)((UITextField *)self.currentFirstResponder).superview.superview;     NSIndexPath *textFieldIndexPath = [_tableView indexPathForCell:textFieldCell];      // iOS 3 sends hide and show notifications right after each another     // when switching between textFields, so cancel -scrollToOldPosition requests     [NSObject cancelPreviousPerformRequestsWithTarreceive :self];     _topmostRowBeforeKeyboardWasShown = [[_tableView indexPathsForVisibleRows] objectAtIndex:0];     [_tableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];   } }  - (void) scrollToOldPosition {   [_tableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES]; }  - (void)keyboardWillHide:(NSNotification*)notification {   if ([self currentFirstResponder] != nil) {      NSDictionary* userInfo = [notification userInfo];      [UIView beginAnimations:nil context:NULL];     [UIView setAnimationDuration:[[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue]];     [UIView setAnimationCurve:[[userInfo objectForKey:UIKeyboardAnimationCurveUserInfoKey] intValue]];     _tableView.frame = self.view.bounds;     [UIView commitAnimations];      [self performSelector:@selector(scrollToOldPosition) withObject:nil afterDelay:0.1];   } }     @end 

10:

Keyboard notifications work, although Apple's sample code for this assumes this the scroll view is the root view of the window. This is usually not the case. You have to compensate for tab bars, etc., to receive the right offset.. It is easier than it sounds. Here is the code I use in a UITableViewController. It has two instance variables, hiddenRect and keyboardShown..
// Called when the UIKeyboardDidShowNotification is sent. - (void)keyboardWasShown:(NSNotification*)aNotification {     if (keyboardShown)         return;      NSDictionary* info = [aNotification userInfo];      // Get the frame of the keyboard.     NSValue *centerValue = [info objectForKey:UIKeyboardCenterEndUserInfoKey];     NSValue *boundsValue = [info objectForKey:UIKeyboardBoundsUserInfoKey];     CGPoint keyboardCenter = [centerValue CGPointValue];     CGRect keyboardBounds = [boundsValue CGRectValue];     CGPoint keyboardOrigin = CGPointMake(keyboardCenter.x - keyboardBounds.size.width / 2.0,                                          keyboardCenter.y - keyboardBounds.size.height / 2.0);     CGRect keyboardScreenFrame = { keyboardOrigin, keyboardBounds.size };       // Resize the scroll view.     UIScrollView *scrollView = (UIScrollView *) self.tableView;     CGRect viewFrame = scrollView.frame;     CGRect keyboardFrame = [scrollView.superview convertRect:keyboardScreenFrame fromView:nil];     hiddenRect = CGRectIntersection(viewFrame, keyboardFrame);      CGRect remainder, slice;     CGRectDivide(viewFrame, &slice, &remainder, CGRectGetHeight(hiddenRect), CGRectMaxYEdge);     scrollView.frame = remainder;      // Scroll the active text field into view.     CGRect textFieldRect = [/* selected cell */ frame];     [scrollView scrollRectToVisible:textFieldRect animated:YES];      keyboardShown = YES; }   // Called when the UIKeyboardDidHideNotification is sent - (void)keyboardWasHidden:(NSNotification*)aNotification {     // Reset the height of the scroll view to its original value     UIScrollView *scrollView = (UIScrollView *) self.tableView;     CGRect viewFrame = [scrollView frame];     scrollView.frame = CGRectUnion(viewFrame, hiddenRect);      keyboardShown = NO; } 

11:

THE RIGHT ANSWER is Sam Ho's answer:. "If you use UITableViewController instead of UIViewController, it will automatically did so.".. Just make sure to connect your UITableView to the TableView property of the UITableViewController (so e.g. did not add it as a subview of the View property of the UITableViewController).. Also make sure to set the AutoresizingMask property of your UITableView to FlexibleHeight.

12:

If you use Three20, then use the autoresizesForKeyboard property. Just set in the your view controller's -initWithNibName:bundle method.
self.autoresizesForKeyboard = YES 
This takes care of:.
  1. Listening for keyboard notifications and adjusting the table view's frame
  2. Scrolling to the first responder
Done and done..

13:

My approach:. I first subclass UITextField and add an indexPath property. In the cellFor... Method i hand over the indexPath property.. Then I add following code:.
UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:textField.indexPath];  CGPoint cellPoint = [cell convertPoint:textField.center toView:self.tableView]; [UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, cellPoint.y-50);}]; 
to the textFieldShould/WillBegin...etc.. When the Keyboard disappears you have to reverse it with:.
[UIView animateWithDuration:0.3 animations:^(void){self.tableView.contentOffset = CGPointMake(0, 0);}]; 

14:

I hope you guys already got a quick fix reading all those. But I found my quick fix as follows. I am expecting this you already have a cell with UITextField. So on preparing just keep the row index into the text field's tag..
cell.textField.tag = IndexPath.row; 
Create an activeTextField, instance of UITextField with global scope as below: .
@interface EditViewController (){      UITextField *activeTextField;  } 
So, now you just copy paste my code at the end. And also don't forreceive to add UITextFieldDelegate.
#pragma mark - TextField Delegation  - (BOOL)textFieldShouldBeginEditing:(UITextField *)textField{      activeTextField = textField;      return YES; }  - (void)textFieldDidEndEditing:(UITextField *)textField{      activeTextField = nil;  } 
Registers keyboard notifications.
#pragma mark - Keyboard Activity  - (void)registerForKeyboardNotifications  {      [[NSNotificationCenter defaultCenter] addObserver:self                                           selector:@selector(keyboardWasShown:)                                               name:UIKeyboardDidShowNotification object:nil];        [[NSNotificationCenter defaultCenter] addObserver:self                                           selector:@selector(keyboardWillBeHidden:)                                               name:UIKeyboardWillHideNotification object:nil];    } 
Handles Keyboard Notifications:. Called when the UIKeyboardDidShowNotification is sent..
- (void)keyboardWasShown:(NSNotification*)aNotification  {      NSDictionary* info = [aNotification userInfo];      CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;      UIEdgeInsets contentInsets = UIEdgeInsetsMake(0.0, 0.0, kbSize.height, 0.0);      [self.tableView setContentInset:contentInsets];      [self.tableView setScrollIndicatorInsets:contentInsets];      NSIndexPath *currentRowIndex = [NSIndexPath indexPathForRow:activeTextField.tag inSection:0];      [self.tableView scrollToRowAtIndexPath:currentRowIndex atScrollPosition:UITableViewScrollPositionTop animated:YES];  } 
Called when the UIKeyboardWillHideNotification is sent.
- (void)keyboardWillBeHidden:(NSNotification*)aNotification  {      UIEdgeInsets contentInsets = UIEdgeInsetsZero;      [self.tableView setContentInset:contentInsets];      [self.tableView setScrollIndicatorInsets:contentInsets];  } 
Now one thing is left, Call the registerForKeyboardNotifications method in to ViewDidLoad method as follows:.
- (void)viewDidLoad {      [super viewDidLoad];      // Registering keyboard notification      [self registerForKeyboardNotifications];      // Your codes here...  } 
You are done, hope your textFields will no longer hidden by the keyboard..

15:

If you use a uitableview to place your textfields (from Jeff Lamarche), you must just scroll the tableview using the delegate method like so. . (Note: my text fields are stored in an array with the same index as there row in the tableview).
- (void) textFieldDidBeginEditing:(UITextField *)textField     {          int index;         for(UITextField *aField in textFields){              if (textField == aField){                 index = [textFields indexOfObject:aField]-1;             }         }           if(index >= 0)              [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:index inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:YES];          [super textFieldDidBeginEditing:textField];     } 

16:

A more stream-lined solution. It slips into the UITextField delegate methods, so it doesn't require messing w/ UIKeyboard notifications.. Implementation notes:. kSettingsRowHeight -- the height of a UITableViewCell.. offsetTarreceive and offsetThreshold are baed off of kSettingsRowHeight. If you use a different row height, set those values to point's y property. [alt: calculate the row offset in a different manner.].
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField { CGFloat offsetTarreceive 	= 113.0f; // 3rd row CGFloat offsetThreshold	= 248.0f; // 6th row (i.e. 2nd-to-last row)  CGPoint point = [self.tableView convertPoint:CGPointZero fromView:textField];  [UIView beginAnimations:nil context:nil]; [UIView setAnimationDuration:0.2]; [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];  CGRect frame = self.tableView.frame; if (point.y > offsetThreshold) { 	self.tableView.frame = CGRectMake(0.0f, 					  offsetTarreceive  - point.y + kSettingsRowHeight, 					  frame.size.width, 					  frame.size.height); } else if (point.y > offsetTarreceive ) { 	self.tableView.frame = CGRectMake(0.0f, 					  offsetTarreceive  - point.y, 					  frame.size.width, 					  frame.size.height); } else { 	self.tableView.frame = CGRectMake(0.0f, 					  0.0f, 					  frame.size.width, 					  frame.size.height); }  [UIView commitAnimations];  return YES; 
}.
- (BOOL)textFieldShouldReturn:(UITextField *)textField { [textField resignFirstResponder];  [UIView beginAnimations:nil context:nil]; [UIView setAnimationBeginsFromCurrentState:YES]; [UIView setAnimationDuration:0.2]; [UIView setAnimationCurve:UIViewAnimationCurveEaseOut];  CGRect frame = self.tableView.frame; self.tableView.frame = CGRectMake(0.0f, 				  0.0f, 				  frame.size.width, 				  frame.size.height);  [UIView commitAnimations];  return YES; 
}.

17:

I ran into any thing like your problem (I wanted a screen similar to the iPhone's settings.app with a bunch of editable cells stacked on on top of another) and found this this approach worked well:. sliding uitextfields around to avoid.

18:

Since you have textfields in a table, the best way really is to resize the table - you need to set the tableView.frame to be smaller in height by the size of the keyboard (I think around 165 pixels) and then expand it again when the keyboard is dismissed.. You must optionally also disable user interaction for the tableView at this time as well, if you did not want the user scrolling..

19:

This soluton works for me, PLEASE note the line.
[tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES]; 
You must change the 160 value to match it job with you.
- (void)keyboardWasShown:(NSNotification*)aNotification {     NSDictionary* info = [aNotification userInfo];     CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;     CGRect bkgndRect = activeField.superview.frame;                         bkgndRect.size.height += kbSize.height;      [activeField.superview setFrame:bkgndRect];      [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height+160) animated:YES]; }  - (void)textFieldDidBeginEditing:(UITextField *)textField {    activeField = textField; } -(void)textFieldDidEndEditing:(UITextField *)textField  {      activeField = nil;  } // Called when the UIKeyboardWillHideNotification is sent - (void)keyboardWillBeHidden:(NSNotification*)aNotification {     UIEdgeInsets contentInsets = UIEdgeInsetsZero;     tableView.contentInset = contentInsets;     tableView.scrollIndicatorInsets = contentInsets;     NSDictionary* info = [aNotification userInfo];     CGSize kbSize = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;     CGRect bkgndRect = activeField.superview.frame;     //bkgndRect.size.height += kbSize.height;     [activeField.superview setFrame:bkgndRect];     [tableView setContentOffset:CGPointMake(0.0, activeField.frame.origin.y-kbSize.height) animated:YES]; } 

20:

Very interesting discussion thread, i also faced the same problem may be worse one because.
  1. I was using a custom cell and the textfield was inside that.
  2. I had to use UIViewController to meet my requirements so cant take advantage of UITableViewController.
  3. I had filter/ sort criterias in my table cell, ie ur cells keeps on changing and keeping track of the indexpath and all will not help.
So read the threads here and implemented my version, which helped me in pushing up my contents in iPad in landscape mode. Here is code ( this is not fool proof and all, although it fixed my issue) First u need to have a delegate in your custom cell class, which on editing begins, sends the textfield to ur viewcontroller and set the activefield = theTextField there. // IMPLEMENTED TO HANDLE LANDSCAPE MODE ONLY.
- (void)keyboardWasShown:(NSNotification*)aNotification {     NSDictionary* info = [aNotification userInfo];     CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;     CGRect aRect = myTable.frame;      CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);      aRect.size.height -= kbSize.height+50; // This will the exact rect in which your textfield is present         CGRect rect =  [myTable convertRect:activeField.bounds fromView:activeField]; // Scroll up only if required     if (!CGRectContainsPoint(aRect, rect.origin) ) {               [myTable setContentOffset:CGPointMake(0.0, rect.origin.y) animated:YES];      }   } 
// Called when the UIKeyboardWillHideNotification is sent.
- (void)keyboardWillHide:(NSNotification*)aNotification {     UIEdgeInsets contentInsets = UIEdgeInsetsZero;     myTable.contentInset = contentInsets;     myTable.scrollIndicatorInsets = contentInsets;     NSDictionary* info = [aNotification userInfo];     CGSize kbValue = [[info objectForKey:UIKeyboardFrameBeginUserInfoKey] CGRectValue].size;     CGSize kbSize = CGSizeMake(kbValue.height, kbValue.width);     CGRect bkgndRect = activeField.superview.frame;     bkgndRect.size.height += kbSize.height;     [activeField.superview setFrame:bkgndRect];     [myTable setContentOffset:CGPointMake(0.0, 10.0) animated:YES]; } 
-anoop4real.

21:

An case in Swift, using the exact point of the text field from Get indexPath of UITextField in UITableViewCell with Swift:.
func textFieldDidBeginEditing(textField: UITextField) {     let pointInTable = textField.convertPoint(textField.bounds.origin, toView: self.accountsTableView)     let textFieldIndexPath = self.accountsTableView.indexPathForRowAtPoint(pointInTable)     accountsTableView.scrollToRowAtIndexPath(textFieldIndexPath!, atScrollPosition: .Top, animated: true) } 

22:

This works perfectly, and on iPad too..
- (BOOL)textFieldShouldReturn:(UITextField *)textField  {      if(textField == textfield1){             [accountName1TextField becomeFirstResponder];         }else if(textField == textfield2){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:0 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield3 becomeFirstResponder];          }else if(textField == textfield3){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:1 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield4 becomeFirstResponder];          }else if(textField == textfield4){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:2 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield5 becomeFirstResponder];          }else if(textField == textfield5){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:3 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield6 becomeFirstResponder];          }else if(textField == textfield6){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:4 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield7 becomeFirstResponder];          }else if(textField == textfield7){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:5 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield8 becomeFirstResponder];          }else if(textField == textfield8){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:6 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textfield9 becomeFirstResponder];          }else if(textField == textfield9){             [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForRow:7 inSection:1] atScrollPosition:UITableViewScrollPositionTop animated:YES];             [textField resignFirstResponder];         } 

23:

So after hours of grueling job endeavor to use these current solutions (and utterly failing) I finally got things working well, and updated them to use the new animation blocks. My answer is entirely based on Ortwin's answer above.. So for whatever reason the code above was just not working for me. My setup seemed fairly similar to others, although maybe for the reason this I was on an iPad or 4.3... no idea. It was doing any wacky math and shooting my tableview off the screen.. See end result of my solution: http://screencast.com/t/hjBCuRrPC (Please ignore the photo. :-P). So I went with the gist of what Ortwin was doing, although changed how it was doing any math to add up the origin.y & size.height of my table view with the height of the keyboard. When I subtract the height of the window from this result , it tells me how enough intersection I have going on. If its greater than 0 (aka there is any overlap) I perform the animation of the frame height. . In addition there were any redraw issues this were solved by 1) Waiting to scroll to the cell until the animation was done and 2) using the UIViewAnimationOptionBeginFromCurrentState option when hiding the keyboard.. A couple things to note. .
  • _topmostRowBeforeKeyboardWasShown & _originalFrame are instance variables declared in the header.
  • self.guestEntryTableView is my tableView (I'm in an external file)
  • IASKCGRectSwap is Ortwin's method for flipping the coordinates of a frame
  • I only update the height of the tableView if at least 50px of it is going to be showing
  • Since I'm not in a UIViewController I don't have self.view, so I just return the tableView to its original frame
Again, I wouldn't have gotten near this answer if I Ortwin didn't provide the crux of it. Here's the code:.
- (IBAction)textFieldDidBeginEditing:(UITextField *)textField {     self.activeTextField = textField;      if ([self.guestEntryTableView indexPathsForVisibleRows].count) {         _topmostRowBeforeKeyboardWasShown = (NSIndexPath*)[[self.guestEntryTableView indexPathsForVisibleRows] objectAtIndex:0];     } else {         // this should never appear         _topmostRowBeforeKeyboardWasShown = [NSIndexPath indexPathForRow:0 inSection:0];         [textField resignFirstResponder];     } }  - (IBAction)textFieldDidEndEditing:(UITextField *)textField {     self.activeTextField = nil; }  - (void)keyboardWillShow:(NSNotification*)notification {     NSDictionary* userInfo = [notification userInfo];      NSValue* keyboardFrameValue = [userInfo objectForKey:UIKeyboardFrameEndUserInfoKey];      // Reduce the tableView height by the part of the keyboard this actually covers the tableView     UIInterfaceOrientation orientation = [[UIApplication sharedApplication] statusBarOrientation];     CGRect windowRect = [[UIApplication sharedApplication] keyWindow].bounds;     CGRect viewRectAbsolute = [self.guestEntryTableView convertRect:self.guestEntryTableView.bounds toView:[[UIApplication sharedApplication] keyWindow]];     CGRect keyboardFrame = [keyboardFrameValue CGRectValue];     if (UIInterfaceOrientationLandscapeLeft == orientation ||UIInterfaceOrientationLandscapeRight == orientation ) {         windowRect = IASKCGRectSwap(windowRect);         viewRectAbsolute = IASKCGRectSwap(viewRectAbsolute);         keyboardFrame = IASKCGRectSwap(keyboardFrame);     }      // fix the coordinates of our rect to have a top left origin 0,0     viewRectAbsolute = FixOriginRotation(viewRectAbsolute, orientation, windowRect.size.width, windowRect.size.height);      CGRect frame = self.guestEntryTableView.frame;     _originalFrame = self.guestEntryTableView.frame;      int remainder = (viewRectAbsolute.origin.y + viewRectAbsolute.size.height + keyboardFrame.size.height) - windowRect.size.height;      if (remainder > 0 && !(remainder > frame.size.height + 50)) {         frame.size.height = frame.size.height - remainder;         float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];         [UIView animateWithDuration: duration                         animations:^{                             self.guestEntryTableView.frame = frame;                         }                         completion:^(BOOL finished){                             UITableViewCell *textFieldCell = (UITableViewCell*) [[self.activeTextField superview] superview];                             NSIndexPath *textFieldIndexPath = [self.guestEntryTableView indexPathForCell:textFieldCell];                             [self.guestEntryTableView scrollToRowAtIndexPath:textFieldIndexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];                         }];     }  }  - (void)keyboardWillHide:(NSNotification*)notification {     NSDictionary* userInfo = [notification userInfo];     float duration = [[userInfo objectForKey:UIKeyboardAnimationDurationUserInfoKey] doubleValue];     [UIView animateWithDuration: duration                           delay: 0.0                         options: (UIViewAnimationOptionBeginFromCurrentState)                      animations:^{                          self.guestEntryTableView.frame = _originalFrame;                      }                      completion:^(BOOL finished){                          [self.guestEntryTableView scrollToRowAtIndexPath:_topmostRowBeforeKeyboardWasShown atScrollPosition:UITableViewScrollPositionTop animated:YES];                      }];  }     #pragma mark CGRect Utility function CGRect IASKCGRectSwap(CGRect rect) {     CGRect newRect;     newRect.origin.x = rect.origin.y;     newRect.origin.y = rect.origin.x;     newRect.size.width = rect.size.height;     newRect.size.height = rect.size.width;     return newRect; }  CGRect FixOriginRotation(CGRect rect, UIInterfaceOrientation orientation, int parentWidth, int parentHeight) {     CGRect newRect;     switch(orientation)     {         case UIInterfaceOrientationLandscapeLeft:             newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), rect.origin.y, rect.size.width, rect.size.height);             break;         case UIInterfaceOrientationLandscapeRight:             newRect = CGRectMake(rect.origin.x, parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);             break;         case UIInterfaceOrientationPortrait:             newRect = rect;             break;         case UIInterfaceOrientationPortraitUpsideDown:             newRect = CGRectMake(parentWidth - (rect.size.width + rect.origin.x), parentHeight - (rect.size.height + rect.origin.y), rect.size.width, rect.size.height);             break;     }     return newRect; } 

24:

Ananother easy method (only works with one section).
//cellForRowAtIndexPath UItextField *tf; [cell addSubview:tf]; tf.tag = indexPath.row; tf.delegate = self;  //textFieldDidBeginEditing:(UITextField *)text [[self.tableView scrollToRowsAtIndexPath:[NSIndexPath indexPathForRow:text.tag in section:SECTIONINTEGER] animated:YES]; 

25:

Here is how I made this work, which is a mixture of Sam Ho and Marcel W's answers, and any of my own bug fixes made to my crappy code. I was using a UITableViewController. The table now resizes correctly when the keyboard is shown.. 1) In viewDidLoad I added:. self.tableView.autoresizingMask = UIViewAutoresizingFlexibleHeight;. 2) I had forgotten to call the super equivalents in viewWillAppear and awakeFromNib. I added these back in..

26:

I have just solved such a problem by myself after I referred a mass of solutions found via Google and Stack Overflow.. First, please assure this you have set up an IBOutlet of your UIScrollView, Then please take a close look at Apple Doc: Keyboard Management. Finally, if you must scroll the background, although the keyboard still covers the Text Fields, please have a look at this piece of code:.
// If active text field is hidden by keyboard, scroll it so it's visible // Your application might not need or want this behavior. CGRect aRect = self.view.frame; aRect.size.height -= kbSize.height;  if (aRect.size.height < activeField.frame.origin.y+activeField.frame.size.height) {      CGPoint scrollPoint = CGPointMake(0.0, activeField.frame.origin.y+activeField.frame.size.height-aRect.size.height);      [scrollView setContentOffset:scrollPoint animated:YES]; 
The main difference between this piece and Apple's lies in the if condition. I believe apple's calculation of scroll distance and condition of whether text field covered by keyboard are not accurate, so I made my modification as above.. Let me know if it works.

27:

Easy and fast solution.. I just scroll to the right cell whenever scrolling happens .
    - (void)scrollViewDidScroll:(UIScrollView *)scrollView  
Assuming I know table now is in this mode "_keepMyCellOnTop" & I know selected cell "_selectedCellIndex" or scroll to selected cell.
- (void)scrollViewDidScroll:(UIScrollView *)scrollView  {      if (_keepMyCellOnTop)     {         [self.tableView scrollToRowAtIndexPath:_selectedCellIndex atScrollPosition:UITableViewScrollPositionTop animated:NO];     } } 
This will prevent scrolling.. Placing the code in -(void) scrollViewDidEndScrollingAnimation:(UIScrollView *)scrollView will result a scroll up and down .

28:

I use this often in my projects. This quick fix works with scrollviews, tableviews or collectionviews and it’s easy to setup. It also automatically hooks up “Next” although tons on the keyboard to switch through the text fields.. Check it here.

29:

I'm using these and they job like a charm:. BSKeyboardControls - BSKeyboardControls github. TPKeyboardAvoiding - TPKeyboardAvoiding github.

30:

Use UITextField's delegate method :.
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {   CGPoint txtFieldPosition = [textField convertPoint:CGPointZero toView:yourTblView];   NSLog(@"Begin txtFieldPosition : %@",NSStringFromCGPoint(txtFieldPosition));   NSIndexPath *indexPath = [yourTblView indexPathForRowAtPoint:txtFieldPosition];    [yourTblView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:YES];    return YES; } 


82 out of 100 based on 47 user ratings 842 reviews

#