Deshabilitar el desplazamiento automático de UITableView al editar UITextField dentro de UITableViewCell

I'm using custom UITableViewCellestá dentro de mi UITableView. Cada uno de estos UITableViewCells is pretty high and contains a UITextField en la parte superior de la aplicación.

When a user taps the UITextField in order to edit it, a keyboard appears and the UITableView scrolls automatically so that the cell is at the top of the screen.

The problem is that this scrolls the UITableView al fondo de la UITableViewCell, not the top. When the UITableViewCell is high and edited the UITextField is at the top so you can't see the UITextField. I know how to scroll the UITableView programmatically, but I just don't know how to disable this automatic scrolling so that I can scroll the UITableView on my own. How can I do this?

preguntado el 09 de marzo de 12 a las 15:03

You figure this out? Running into the same problem. -

@SteveBaughman have you found solution? -

nope :( i actually stopped using table view for because of this and some other reasons ... :/ -

It's definitely an issue with UITableViewController's automatic behaviors. -

9 Respuestas

The autoscroll-behavior is located in the UITableViewController funcionalidad

To disable the automatic scrolling I found two ways:

  1. Use instead of the UITableViewController simplemente un UIViewController - set the datasource and delegate on your own.
  2. Anular el viewWillAppear method and don't call [super viewWillAppear: animated]

With both solution you disable not only the Autoscroll, but also some other nice but not essential features, that are described in the overview of Apple´s class reference:

https://developer.apple.com/documentation/uikit/uitableviewcontroller

Respondido el 29 de junio de 17 a las 15:06

I had the same problem and solution 2 worked. I've tested this in iOS 5.0.0 and upwards and it holds so far (current release is 6.1.2). I can't vouch for it in 4 but hey, it's 2013, so we can probably say 5.0 is the lowest supported os right now. - Cocoadelica

Problem with this is that the insets are not adapted to accommodate the keyboard, at least not in iOS 7.0.6. This means that more code will be needed to do this by hand: catching keyboard notifications, ... Ugly. - el significado importa

Can't believe I didn't know about this till today.. I was having problems with TPKeyboardAvoiding.. Thanks!! - Fidel López

Point no2 works on 9.1. Good answer @Dominic. Thanks - pkc456

I wouldn't ever override viewWillAppear: without calling super. UITableViewController subclasses UIViewController, and Apple "requires" all UIViewController subclasses to call super. From the Documentación de UIViewController: "If you override this method, you must call super at some point in your implementation." - ryanipete

Define properties for your UITableViewController:

@property (nonatomic) BOOL scrollDisabled;
@property (nonatomic) CGFloat lastContentOffsetY;

Antes de llamar becomeFirstResponder:

// Save the table view's y content offset 
lastContentOffsetY = tableViewController.tableView.contentOffset.y;
// Enable scrollDisabled
scrollDisabled = YES;

Add the following code to your table view controller:

-(void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (self.scrollDisabled) {
        [self.tableView setContentOffset:CGPointMake(0, lastContentOffsetY)];
    }
    ...
}

Después de llamar resignFirstResponderestablecer scrollDisabled = NO.

respondido 01 nov., 16:19

This isn't a scrollview problem, is a tableViewController class. The correct answer was the override viewWilAppear - Sophy Swicz

Puede hacer lo siguiente:

- (void)registerForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillShow:)
                                                 name:UIKeyboardWillShowNotification object:nil];

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardDidShow:)
                                                 name:UIKeyboardDidShowNotification object:nil];
}

- (void)unregisterForKeyboardNotifications
{
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardWillShowNotification object:nil];
    [[NSNotificationCenter defaultCenter] removeObserver:self name:UIKeyboardDidShowNotification object:nil];
}

- (void)keyboardWillShow:(NSNotification *)notification
{
    self.tableView.scrollEnabled = NO;
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    double delayInSeconds = 0.3;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(delayInSeconds * NSEC_PER_SEC));
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){
            self.tableView.scrollEnabled = YES;
    });
}

Then implement this UIScrollViewDelegate method

- (void)scrollViewDidScroll:(UIScrollView *)scrollView
{
    if (! self.tableView.scrollEnabled)
        [self.tableView scrollToRowAtIndexPath:[NSIndexPath indexPathForItem:0 inSection:0] atScrollPosition:UITableViewScrollPositionTop animated:NO];
}

!!! But be warned, that if the user taps in a location in the UITextField that will be covered by the Keyboard, then it won't scroll.

From my point of view, the best thing to do is to make sure that all the cells from top to then one with the UITextField included, will be visible when then Keyboard will show.

Respondido 12 Abr '13, 14:04

-scrollViewDidScroll: does indeed get called when automatic scrolling happens, this here is the best solution - Nikolái Spassov

The best way is to subclass UITableView y luego anular setContentOffset(_ contentOffset: CGPoint, animated: Bool) and not to call super.setContentOffset(_ contentOffset: CGPoint, animated: Bool). In this method is where the view controller is doing the automatic scroll.

override func setContentOffset(_ contentOffset: CGPoint, animated: Bool)
{
    //Do nothing
}

Respondido el 15 de diciembre de 16 a las 17:12

This was the correct answer for me for a UITableView with UITextView in the cells. - Olle Lind

You could disable the automatic content inset adjustment like so:

tableView.contentInsetAdjustmentBehavior = .never

Respondido el 22 de enero de 20 a las 12:01

This won't work as the keyboard will obscure the cells beneath it. - Felix Marianayagam

The issue for me was not so much that it scrolled but that it took the text view being edited off the screen.

So instead of preventing the scrolling, I just rescroll the tableview to where I want when the editing is triggered, like this:

public func textViewShouldBeginEditing(textView: UITextView) -> Bool {            
  dispatch_async(dispatch_get_main_queue()) {
    tableViewController.tableView.scrollToRowAtIndexPath(self.indexPath!, atScrollPosition: UITableViewScrollPosition.Middle, animated: true)
  }
  return true
}

Respondido 27 Feb 15, 22:02

Unfortunately, overriding -viewWillAppear: doesn't work for me in iOS 8.

Here is my solution (as in UITableViewController implementation):

- (void)viewDidLoad {

[super viewDidLoad];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillShowNotification object:nil];

[[NSNotificationCenter defaultCenter] removeObserver:self.tableView name:UIKeyboardWillHideNotification object:nil];
}

Since the auto-scrolling behaviour is invoked by UIKeyboard's show/hide notifications, so just NOT observe them.

Respondido 03 Abr '15, 09:04

is this still working for you? Can't get it working in iOS 11 / Xcode 9 - Simonthumper

Did you try to set "scrollsToTop" - tableview's property to NO. By default it is YES.

respondido 10 mar '12, 16:03

tried it yet, but it didn't work...scrollToTop doesn't handle this... thanks for answer anyway! - barbilla_animal

You can try doing the following:

self.tableView.scrollEnabled = NO;

This should disable the scrollview in the tableview.

Respondido el 24 de diciembre de 12 a las 01:12

This does not prevent the automatic scrolling the UITableViewController does when tapping on a text field within a UITableViewCell - Gujamín

No es la respuesta que estás buscando? Examinar otras preguntas etiquetadas or haz tu propia pregunta.