28

I have tried most of the examples here on StackOverflow. I also used Apple's. The problem I seem to have with them is that they don't account for the UITextField being in a UITableView. I've done this many times, but not in this way. I have a custom UITableViewCell with a UITextField in it.

On my UITableView (which is NOT a UITableViewController), I need to be able to avoid hiding the UITextField under the UITableView.

I have this as of now:

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

    [[NSNotificationCenter defaultCenter] addObserver:self
                                             selector:@selector(keyboardWillHide:)
                                                 name:UIKeyboardWillHideNotification
                                               object:nil];

....
}

- (void)scrollToRectOfTextField {
    UITableViewCell *cell = (UITableViewCell*)[self.activeTextField superview];
    CGRect r = CGRectMake(self.activeTextField.frame.origin.x,
                          cell.frame.origin.y+self.activeTextField.frame.origin.y,
                          self.activeTextField.frame.size.width,
                          self.activeTextField.frame.size.height);
    [self.tableView scrollRectToVisible:r animated:YES];
}

- (void)keyboardDidShow:(NSNotification *)notification
{
    if (UI_USER_INTERFACE_IDIOM()== UIUserInterfaceIdiomPhone) {
        NSDictionary *userInfo = [notification userInfo];
        CGSize size = [[userInfo objectForKey:UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
        NSLog(@"TableView: %@", NSStringFromCGRect(self.tableView.frame));
        CGRect newTableViewFrame = CGRectMake(self.tableView.frame.origin.x,
                                              self.tableView.frame.origin.y,
                                              self.tableView.frame.size.width, self.tableView.frame.size.height - size.height);
        self.tableView.frame = newTableViewFrame;
        NSLog(@"New TableView: %@", NSStringFromCGRect(self.tableView.frame));


        self.tableView.contentSize = CGSizeMake(self.tableView.contentSize.width, self.tableView.contentSize.height-size.height);
    }
}


- (void)keyboardWillHide:(NSNotification *)notification
{
    NSDictionary *userInfo = [notification userInfo];
    CGSize size = [[userInfo objectForKey: UIKeyboardFrameEndUserInfoKey] CGRectValue].size;
    self.tableView.frame = CGRectMake(self.tableView.frame.origin.x,
                                      self.tableView.frame.origin.y,
                                      self.tableView.frame.size.width,
                                      self.tableView.frame.size.height + size.height);

    NSLog(@"%@", NSStringFromCGRect(self.tableView.frame));
}


-(void)textFieldDidBeginEditing
{
     [self scrollToRectOfTextField];
}

This seems to push a bunch of white space up past my keyboard. Please also note that I have an inputAccessoryView on my UITextField as well.

Oh, and I cannot use any third party classes. I love TPKeyboardAvoidingScrollView, but I cannot use anything third party.

Matt Hudson
  • 7,329
  • 5
  • 49
  • 66
  • When do you call `[self scrollToRectOfTextField];`? – Aaron Brager Feb 23 '13 at 03:00
  • Also, you'll get much smoother animation if you animate the bottom edge inset of the tableview instead of trying to change the frame. – Aaron Brager Feb 23 '13 at 03:01
  • That's a great question. It's not being used in the example I pulled it from. – Matt Hudson Feb 23 '13 at 03:08
  • I edited it. It is called in textFieldDidBeginEditing. – Matt Hudson Feb 23 '13 at 03:12
  • that should be `- (void)textFieldDidBeginEditing:(UITextField *)textField` - have you set a breakpoint there to see if it's getting called? – Aaron Brager Feb 23 '13 at 03:21
  • Also, self.activeTextField's frame is in terms of its superview (the cell it's in.) However, when you call `tableView scrollRectToVisible: animated:` you're not translating that to be in terms of the tableview. Take a look at `-[UIView convertRect: toView:]`. – Aaron Brager Feb 23 '13 at 03:23
  • Thanks Aaron! That is definitely what I was doing wrong. I missed that the superview is a content view and not a UITableViewCell. – Matt Hudson Feb 23 '13 at 03:34
  • Have a look at the open source library TPKeyboardAvoiding here :https://github.com/michaeltyson/TPKeyboardAvoiding – danielbeard Feb 23 '13 at 06:28
  • @danielbeard if you notice, I wrote that I love that class, but cannot use it do to business constraints. – Matt Hudson Feb 23 '13 at 15:03

11 Answers11

53

I spent all day trying to figure this out. I posted it here, then found a blog link and an incredibly simple solution. It looks like this:

-(BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
    CGPoint pointInTable = [textField.superview convertPoint:textField.frame.origin toView:self.tableView];
    CGPoint contentOffset = self.tableView.contentOffset;

    contentOffset.y = (pointInTable.y - textField.inputAccessoryView.frame.size.height);

    NSLog(@"contentOffset is: %@", NSStringFromCGPoint(contentOffset));

    [self.tableView setContentOffset:contentOffset animated:YES];

    return YES;
}


-(BOOL)textFieldShouldEndEditing:(UITextField *)textField
{
    [textField resignFirstResponder];

    if ([textField.superview.superview isKindOfClass:[UITableViewCell class]])
    {
        UITableViewCell *cell = (UITableViewCell*)textField.superview.superview;
        NSIndexPath *indexPath = [self.tableView indexPathForCell:cell];

        [self.tableView scrollToRowAtIndexPath:indexPath atScrollPosition:UITableViewScrollPositionMiddle animated:TRUE];
    }

    return YES;
}

Check this for iOS 8

Hector
  • 3,909
  • 2
  • 30
  • 46
Matt Hudson
  • 7,329
  • 5
  • 49
  • 66
  • I got it to work, but I had to remove the If statements for ShouldEndEditing. Also, if you need have multiple textfields like I did, you'll have to also implement textFieldDidBeginEditing and textFieldDidEndEditing. Just copy and paste the same code as ShouldBegin and ShouldEnd. This will allow the user to jump from textField to textField while keeping the same functionality. If you are struggling w/NSIndexPath, here is a way that's compatible with any version of iOS: http://stackoverflow.com/questions/9577392/uitextfield-subview-of-uitableviewcell-get-indexpath-of-cell/9577406#9577406 – user1107173 Jul 09 '13 at 22:53
  • 1
    Do not use chain of superviews. This is not reliable design. Use the dictionary of indexPaths and textField views tags instead, to find to what text field is next responder and make it firstResponder. – Eugene P Jul 15 '15 at 13:00
  • 1
    This doesn't work if you call `becomeFirstResponder` on the textfield instead of tap it. – Babiker Nov 05 '15 at 06:34
  • What if we are using textfield in multiple subviews? – Jayeshkumar Sojitra May 25 '16 at 07:53
  • Don't forget to add "textFieldShouldReturn:" – arango_86 Jul 02 '16 at 11:03
  • 1
    Agreed with @EugeneProkoshev. This code is bad. Though it has many points and even accepted. If Apple change their tableview subviews hierarchy in future iOS, this code will break for sure (ie crash app). – GeneCode Apr 21 '17 at 11:08
  • @Matt Hudson : This code works as expected, but when device setting >> keyboard >> predictive is on it crops last tableview cell in half. Is there any way to avoid that? – User_1191 Nov 06 '17 at 09:23
  • Unfortunately I wrote this 4 years ago and that predictive keyboard wasn't around then. You could try adjusting the content offset slightly. – Matt Hudson Nov 09 '17 at 03:04
  • Somehow this answer continues to live on. – Matt Hudson Jul 29 '18 at 02:15
25

I tried the link that @inturbidus posted for iOS8 but unfortunately it did not work for me. After a bit of digging, it turns out that Apple does have sample code on their website to make this work naturally as they do in the UITableViewController. Here's the Apple link for the Objective-C version and I'm also adding the swift version here.

Objective-C link from Apple (Scroll to listing 5-1): https://developer.apple.com/library/ios/documentation/StringsTextFonts/Conceptual/TextAndWebiPhoneOS/KeyboardManagement/KeyboardManagement.html

Swift adaptation of the Objective-C Version

var activeField: UITextField?

func textFieldDidBeginEditing(textField: UITextField) {
    self.activeField = textField
}

func textFieldDidEndEditing(textField: UITextField) {
    self.activeField = nil
}

func registerForKeyboardNotifications() {
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWasShown:", name: UIKeyboardDidShowNotification, object: nil)
    NSNotificationCenter.defaultCenter().addObserver(self, selector: "keyboardWillBeHidden:", name: UIKeyboardWillHideNotification, object: nil)
}    

func keyboardWasShown(aNotification: NSNotification) {
    let info = aNotification.userInfo as! [String: AnyObject],
    kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size,
    contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0)

    self.tableView.contentInset = contentInsets
    self.tableView.scrollIndicatorInsets = contentInsets

    // If active text field is hidden by keyboard, scroll it so it's visible
    // Your app might not need or want this behavior.
    var aRect = self.view.frame
    aRect.size.height -= kbSize.height

    if !CGRectContainsPoint(aRect, activeField!.frame.origin) {
        self.tableView.scrollRectToVisible(activeField!.frame, animated: true)
    }
}

func keyboardWillBeHidden(aNotification: NSNotification) {
    let contentInsets = UIEdgeInsetsZero
    self.tableView.contentInset = contentInsets
    self.tableView.scrollIndicatorInsets = contentInsets
}
David
  • 3,285
  • 1
  • 37
  • 54
Salman Hasrat Khan
  • 1,971
  • 1
  • 20
  • 27
  • I didn't add the link, @Hector did. – Matt Hudson Aug 09 '15 at 14:43
  • 1
    I know this is an old answer but I'd like to add for anyone who encounters this: my tableview did not covered the entire view to the bottom I had to correct the kbSize.height with a little margin because only a part of the UITableView is covered by the keyboard. If I used this solution the row scrolled out of the UITableView and was not visible. So this line `contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0)` in the `keyboardWasShow` changes to `UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height-margin, right: 0)`. – Peter Eysermans May 09 '17 at 19:40
11

I made a mix with the answers of Matt and also Salman. This works for many textfields in a tableView. Swift 3

Basically is get the BOTTOM Y point of the textInput touched. Once we have that I check if the keyboard cover the textInput and if do it I would change the contentOffset of the tableView

First register to the notifications. In the init if is a UIView or in viewDidLoad if is a UIViewController:

    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShow), name: NSNotification.Name.UIKeyboardWillShow, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide), name: NSNotification.Name.UIKeyboardWillHide, object: nil)

Then set up the textfield touched as current input

var inputActive: UITextField!

func textViewShouldBeginEditing(_ textView: UITextView) -> Bool {
    inputActive = textInput
    return true
}

Finally implement the notifications method:

func keyboardWillShow(notification: NSNotification) {
    var userInfo = notification.userInfo!
    if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
        // Get my height size
        let myheight = tableView.frame.height
        // Get the top Y point where the keyboard will finish on the view
        let keyboardEndPoint = myheight - keyboardFrame.height
        // Get the the bottom Y point of the textInput and transform it to the currentView coordinates.
        if let pointInTable = inputActive.superview?.convert(inputActive.frame.origin, to: tableView) {
            let textFieldBottomPoint = pointInTable.y + inputActive.frame.size.height + 20
            // Finally check if the keyboard will cover the textInput
            if keyboardEndPoint <= textFieldBottomPoint {
                tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint
            } else {
                tableView.contentOffset.y = 0
            }
        }
    }
}

func keyboardWillHide(notification: NSNotification) {
    tableView.contentOffset.y = 0
}

Few things to add. The padding is some extra distance that I add in my case was 20 points. Also in my case the UITableView was added to a UIViewController but this should work also in a UITableViewController

Hope this helps!

chiri
  • 153
  • 1
  • 6
  • I think it would be beneficial to you to explain a little more at how your code works and what it's doing. – GrumpyCrouton Jun 09 '17 at 17:40
  • @GrumpyCrouton thanks for the advice. I added a few comments on the code and also a little explanation of what I do. =] – chiri Jun 09 '17 at 18:20
  • Thanks, worked with a table with many sections and rows. I changed: var inputActive: UITextView! and this: func textViewShouldBeginEditing(_ textView: UITextView) -> Bool { inputActive = textView return true } – Jeremy Andrews Oct 30 '17 at 16:00
8

Thank @Salman for the link.
Just notice that Apple example is used for scrollview in normal view.
In table view you must convert Point and Rect of activeField to table's coordinate, so I change some lines in function keyboardWasShown:

func keyboardWasShown(aNotification: NSNotification) {
        let info = aNotification.userInfo as! [String: AnyObject],
        kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).CGRectValue().size,
        contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0)

        self.tableBasket.contentInset = contentInsets
        self.tableBasket.scrollIndicatorInsets = contentInsets

        var aRect = self.view.frame
        aRect.size.height -= kbSize.height

        let pointInTable = activeField!.superview!.convertPoint(activeField!.frame.origin, toView: tableView)
        let rectInTable = activeField!.superview!.convertRect(activeField!.frame, toView: tableView)

        if !CGRectContainsPoint(aRect, pointInTable) {
            self.tableView.scrollRectToVisible(rectInTable, animated: true)
        }
}

And if your view has tabBarController, remember to reset contentInsets with tabBar height instead of UIEdgeInsetsZero (if not, your last bottom rows maybe hiden under tabBar):

func keyboardWillBeHidden(aNotification: NSNotification) {
        //UIEdgeInsetsZero is used in view without tabBar
        //let contentInsets = UIEdgeInsetsZero
        let tabBarHeight = self.tabBarController!.tabBar.frame.height
        let contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: tabBarHeight, right: 0)
        self.tableView.contentInset = contentInsets
        self.tableView.scrollIndicatorInsets = contentInsets
    }
}
Nhan Lam Dai
  • 81
  • 1
  • 1
  • thanks. I have rewritten the code to Obj-C and it fixed the issues with Apple's code while using tableview. – skornos Oct 07 '15 at 11:54
  • BTW: if you are using self.edgesForExtendedLayout = UIRectEdgeNone then it is not necessary to change keyboardWillBeHidden as mentioned here – skornos Oct 07 '15 at 12:02
5

My solution (worked on Xcode 8.3.3, Swift 3, iOS 10.3.1):

class MyTableViewController: UITableViewController {

    override func viewWillAppear(_ animated: Bool) {
        NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardDidShow(with:)), name: .UIKeyboardDidShow, object: nil)
        NotificationCenter.default.addObserver(self, selector: #selector(actionKeyboardWillHide(with:)), name: .UIKeyboardWillHide, object: nil)
    }

    override func viewDidDisappear(_ animated: Bool) {
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardDidShow, object: nil)
        NotificationCenter.default.removeObserver(self, name: .UIKeyboardWillHide, object: nil)
    }

    @objc private func actionKeyboardDidShow(with notification: Notification) {
        guard let userInfo = notification.userInfo as? [String: AnyObject],
            let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
            else { return }

        var contentInset = self.tableView.contentInset
        contentInset.bottom += keyboardFrame.height

        self.tableView.contentInset = contentInset
        self.tableView.scrollIndicatorInsets = contentInset
    }

    @objc private func actionKeyboardWillHide(with notification: Notification) {
        guard let userInfo = notification.userInfo as? [String: AnyObject],
            let keyboardFrame = (userInfo[UIKeyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
            else { return }

        var contentInset = self.tableView.contentInset
        contentInset.bottom -= keyboardFrame.height

        self.tableView.contentInset = contentInset
        self.tableView.scrollIndicatorInsets = contentInset
    }

}
jqgsninimo
  • 6,562
  • 1
  • 36
  • 30
  • I think you want UIKeyboardFrameEndUserInfoKey in your DidShow. Begin is the frame at the beginning of the animation – Aneel Nov 27 '17 at 14:30
3

I did a mix between the answer of @Victor and some code that I had. I created a handy extension that can be use across many UITextField.

1.- First we need an extension for the UITextField to manage the keyboard notifications

extension UITextField {

    func keepTextFieldAboveKeyboard(tableView:UITableView) {

        var willShowNotification: NSObjectProtocol?
        var willHideNotification: NSObjectProtocol?

        willShowNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in

            var userInfo = notification.userInfo!

            if let keyboardFrame = (userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue)?.cgRectValue {
                // Get my height size
                let myheight = tableView.frame.height
                // Get the top Y point where the keyboard will finish on the view
                let keyboardEndPoint = myheight - keyboardFrame.height
                // Get the the bottom Y point of the textInput and transform it to the currentView coordinates.
                if let pointInTable = self.superview?.convert(self.frame.origin, to: tableView) {

                    let textFieldBottomPoint = pointInTable.y + self.frame.size.height + 20

                    // Finally check if the keyboard will cover the textInput
                    if keyboardEndPoint <= textFieldBottomPoint {

                        tableView.contentOffset.y = textFieldBottomPoint - keyboardEndPoint
                    } else {

                        tableView.contentOffset.y = 0
                    }
                }
            }

            NotificationCenter.default.removeObserver(willShowNotification!)
        }

        willHideNotification = NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in

            tableView.contentOffset.y = 0

            NotificationCenter.default.removeObserver(willHideNotification!)
        }

    }

}

2.- This previous extension should be call inside textFieldShouldBeginEditing so we can have an extension for that as well

extension UITextField : UITextFieldDelegate {

    public func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool  {

        guard let tableView = textField.parentView(of: UITableView.self) else { return true };

        textField.keepTextFieldAboveKeyboard(tableView:tableView);

        return true;

    }
}

3.- Finally as you notice in the previous method, we need the TableView where the cell with the UITextField is located. So we can use this extension (Which is also useful for other purposes)

extension UIView {
    func parentView<T: UIView>(of type: T.Type) -> T? {
        guard let view = self.superview else {
            return nil
        }
        return (view as? T) ?? view.parentView(of: T.self)
    }
}

4.- Finally in the cell where the UITextField is located, we just write this simple line of code

textField.delegate = textField;

Completely reusable and universal.

Joaquin Pereira
  • 311
  • 2
  • 14
2

This answer is for Xamarin iOS users, however someone can easily modify it to make it work with Swift or Objective C.

The solution is very simple and has worked perfectly in my case where I needed a cell to appear on the top half of the screen in order for the cell's textfield to be above keyboard. So what I did is the following:

I implemented textField.ShouldBeginEditing the following way:

myTextField.ShouldBeginEditing = textField =>
{
   myTableView.ScrollToRow(indexPath, UITableViewScrollPosition.Top, true);

   return true;
};

Where:

myTextField is the cell's text field,

myTableView is the table view,

indexPath is the cell's index path within the table view.

As I previously mentioned, this solution works perfectly in my case so I thought I could share it with you guys in case it works for you as well. Happy coding :)

2

jqgsninimo's solution updated to 4.2. Works on iOS 12.0.

Swift 4.2

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardDidShow(with:)), name: UIResponder.keyboardDidShowNotification, object: nil)
    NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHide(with:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}

override func viewWillDisappear(_ animated: Bool) {
    super.viewWillDisappear(animated)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardDidShowNotification, object: nil)
    NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}

@objc func keyboardDidShow(with notification: Notification) {
    guard let userInfo = notification.userInfo as? [String: AnyObject],
        let keyboardFrame = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        else { return }

    var contentInset = self.tableView.contentInset
    contentInset.bottom += keyboardFrame.height

    tableView.contentInset = contentInset
    tableView.scrollIndicatorInsets = contentInset
}

@objc func keyboardWillHide(with notification: Notification) {
    guard let userInfo = notification.userInfo as? [String: AnyObject],
        let keyboardFrame = (userInfo[UIResponder.keyboardFrameBeginUserInfoKey] as? NSValue)?.cgRectValue
        else { return }

    var contentInset = self.tableView.contentInset
    contentInset.bottom -= keyboardFrame.height

    tableView.contentInset = contentInset
    tableView.scrollIndicatorInsets = contentInset
}
Jayden Irwin
  • 921
  • 9
  • 14
  • 1
    This only add content insets for keyboard, which means you can scroll to bottom of tablview without resigning keyboard. But it does not have any code for focusing to active textfield. – Amber K Dec 11 '18 at 14:01
1

Scroll UITextField above Keyboard in a UITableViewCell on a regular UIViewController swift 3 and Xcode 8.1

1) set Delegate = UITextFieldDelegate

  override func viewWillAppear(_ animated: Bool) {

        NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillShow), name:NSNotification.Name.UIKeyboardWillShow, object: nil);
        NotificationCenter.default.addObserver(self, selector: #selector(DayViewController.keyboardWillHide), name:NSNotification.Name.UIKeyboardWillHide, object: nil);

   }
      func textFieldDidBeginEditing(_ textField: UITextField) {
          self.activeField = textField
   }
      func textFieldDidEndEditing(_ textField: UITextField) {
        self.activeField = nil
   }


//MARK: - Keyboard Show and Hide Methods
    func keyboardWillShow(notification: NSNotification)
    {
        let info = notification.userInfo! as! [String: AnyObject],
        kbSize = (info[UIKeyboardFrameBeginUserInfoKey] as! NSValue).cgRectValue.size,
        contentInsets = UIEdgeInsets(top: 0, left: 0, bottom: kbSize.height, right: 0)

        self.FourthTblMainTableView.contentInset = contentInsets
        self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets

        var aRect = self.FourthTblMainTableView.frame
        aRect.size.height -= kbSize.height
    }
    func keyboardWillHide(notification: NSNotification)
    {
         let contentInsets = UIEdgeInsets.zero
        self.FourthTblMainTableView.contentInset = contentInsets
        self.FourthTblMainTableView.scrollIndicatorInsets = contentInsets
    }
Parth Changela
  • 955
  • 2
  • 8
  • 6
1

Converted @Matt Hudsons answer to Swift 4.2 and improved with a delegate:

func cell(_ cell: UITableViewCell, willStartEditing view: UIView) {
    if let inputAccessoryViewHeight = view.inputAccessoryView?.frame.size.height {
        var contentOffset = self.tableView.contentOffset
        let pointInTable = view.convert(view.frame.origin, to: self.tableView)
        
        contentOffset.y = pointInTable.y - inputAccessoryViewHeight
        
        self.tableView.setContentOffset(contentOffset, animated: true)
    }
}

func cell(_ cell: UITableViewCell, willEndEditing view: UIView) {
    view.resignFirstResponder()
    
    if let position = self.tableView.indexPath(for: cell) {
        self.tableView.scrollToRow(at: position, at: .middle, animated: true)
    }
}

Implement the UITextFieldDelegate in your UITableViewCell and pass the UITextField like the following:

func textFieldShouldBeginEditing(_ textField: UITextField) -> Bool {
    delegate?.cell(self, willStartEditing: textField)
    return true
}

func textFieldShouldEndEditing(_ textField: UITextField) -> Bool {
    delegate?.cell(self, willEndEditing: textField)
    return true
}
paderick
  • 11
  • 2
0

In swift4 we can create an extension of UIViewController.

extension UIViewController {
    //MARK: Keyboard user interactions
    func handleContainerViewFrameOnKeyboardShowHide(originalContainerFrame: CGRect) {
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillShow, object: nil, queue: OperationQueue.main) {(notification) in
            var info = (notification as NSNotification).userInfo!
            let keyboardFrame: CGRect = (info[UIKeyboardFrameEndUserInfoKey] as! NSValue).cgRectValue
            var tableViewFrame = originalContainerFrame
            tableViewFrame.size.height = originalContainerFrame.size.height - keyboardFrame.size.height
            self.view.frame = tableViewFrame
        }
        NotificationCenter.default.addObserver(forName: NSNotification.Name.UIKeyboardWillHide, object: nil, queue: OperationQueue.main) { (notification) in
            self.view.frame = originalContainerFrame
        }
    }
}
Susim Samanta
  • 1,605
  • 1
  • 14
  • 30