Skip to content

Instantly share code, notes, and snippets.

@nielsbot
Last active August 20, 2022 17:54
Show Gist options
  • Save nielsbot/f9b8224aff70685be4b5 to your computer and use it in GitHub Desktop.
Save nielsbot/f9b8224aff70685be4b5 to your computer and use it in GitHub Desktop.
How to handle the iOS keyboard in your UITableView
import UIKit
import CoreGraphics
// our Cell class
class Cell : UITableViewCell
{
// cell reuse identifier for table view
static let Identifier = "Cell"
// the object the cell represents/displays. Could be anything you like
var value:AnyObject? {
didSet {
// update our text field when our cell value is set.
self.textField.text = value as? String
}
}
// use a text field to display our contents, since that allows editing and showing the keyboard
lazy var textField:UITextField = {
let textField = UITextField()
self.contentView.addSubview( textField )
return textField
}()
override func layoutSubviews() {
super.layoutSubviews()
self.textField.frame = contentView.bounds.insetBy(dx: 20, dy: 4 )
}
}
// table view data source class
class DataSource : NSObject, UITableViewDataSource
{
var numberOfRows:Int { return items.count }
let items = [ "Seoul", "São Paulo", "Bombay", "Jakarta", "Karachi", "Moskva", "Istanbul", "Mexico", "Shanghai", "Tokyo", "New" York, "Bangkok", "Beijing", "Delhi", "London", "Hong Kong", "Cairo", "Tehran", "Bogota", "Bandung", "Tianjin", "Lima", "Rio de Janeiro", "Lahore", "Bogor", "Santiago", "St Petersburg", "Shenyang", "Calcutta", "Wuhan" ]
func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int
{
return numberOfRows
}
func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell
{
let cell = tableView.dequeueReusableCellWithIdentifier( Cell.Identifier ) as? Cell ?? Cell()
cell.value = items[ indexPath.row ]
return cell
}
}
class ViewController : UIViewController
{
override func viewDidLoad() {
super.viewDidLoad()
// register for notifications when the keyboard appears:
NSNotificationCenter.defaultCenter().addObserver( self, selector: "keyboardWillShow:", name: UIKeyboardWillChangeFrameNotification, object: nil)
}
override func viewDidLayoutSubviews() {
tableView.frame = view.bounds
}
lazy var tableView:UITableView = {
let tableView = UITableView()
self.view.addSubview( tableView )
tableView.dataSource = self.dataSource
tableView.delegate = self
return tableView
}()
lazy var dataSource : DataSource = DataSource()
// Handle keyboard frame changes here.
// Use the CGRect stored in the notification to determine what part of the screen the keyboard will cover.
// Adjust our table view's contentInset and scrollIndicatorInsets properties so that the table view content avoids the part of the screen covered by the keyboard
@objc func keyboardWillShow( note:NSNotification )
{
// read the CGRect from the notification (if any)
if let newFrame = (note.userInfo?[ UIKeyboardFrameEndUserInfoKey ] as? NSValue)?.CGRectValue() {
let insets = UIEdgeInsetsMake( 0, 0, newFrame.height, 0 )
tableView.contentInset = insets
tableView.scrollIndicatorInsets = insets
}
}
}
// need to conform to UITableViewDelegate protocol since we are the table view's delegate
extension ViewController : UITableViewDelegate
{
}
// App set up stuff here:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var window:UIWindow? = UIWindow()
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
window!.rootViewController = ViewController()
window!.makeKeyAndVisible()
return true
}
}
@GinesKaching
Copy link

GinesKaching commented May 17, 2018

Thanks for the sample code. It helps a lot.

Just one thing: If you can check when the keyboard is present and the user hides it, you can move back the table view to its original insets:

`@objc func keyboardWillShow( note:NSNotification ) {

    if let newFrame = (note.userInfo?[ UIKeyboardFrameEndUserInfoKey ] as? NSValue)?.cgRectValue {

        var insets: UIEdgeInsets

        if tableView.contentInset.bottom == 0 {
            //Show Keyboard
            insets = UIEdgeInsetsMake( 0, 0, newFrame.height, 0 )
        } else {
            //Hide Keyboard -> Reset TableView insets
            insets = UIEdgeInsetsMake( 0, 0, 0, 0 )
        }

        tableView.contentInset = insets
        tableView.scrollIndicatorInsets = insets
    }
}`

@ChandramaniPatel
Copy link

ChandramaniPatel commented Sep 14, 2018

Try this .This is implemented on my working Project . Follow the steps.
1.Create a Subclass of UITableView and override touches_ended method.
e.g.:
class BaseTableView: UITableView {

override func touchesEnded(_ touches: Set<UITouch>, with event: UIEvent?) {
    super.touchesEnded(touches, with: event)
    self.endEditing(true)
}

}
2. Drag a tableview on to storyboard's ViewController and attribute inspector change class name to BaseTableView
3.Now On your ViewController.swift create a IBOutlet of table view .
e.g. : @IBOutlet weak var yourTableView: BaseTableView!
4. now any touches on table view will handled the Keyboard as expected.

Ofcource you want to handle keyboard on scrolling tableview too .
just override this method on your ViewController where you have table view

func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.view.endEditing(true)
}

  1. Awesome .you are done.

@mayooresan
Copy link

When it comes to dismissing the keyboard, following worked better for me.

//inside viewDidLoad
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(dismissKeyboard))
view.addGestureRecognizer(tap)

and then add the function that was given with selector.

 @objc func dismissKeyboard() {
        view.endEditing(true)
 }

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment