I have a tableView in my view controller and I have it such that the tableView shrinks and expands depending on whether the keyboard is on the screen or off the screen. When the tableView shrinks, I want it to scroll to the bottom row but I can't get this to work.
Currently, I have the following:
@objc func keyboardAppears(notification: Notification) {
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
bottomConstraint.constant = -1 * keyboardFrame.height
view.loadViewIfNeeded()
tableView.scrollToRow(at: IndexPath(row: 10, section: 0), at: .top, animated: true)
}
}
I also tried putting it in the main thread. This got it to work the first time the keyboard went up only. The code looked as follows:
@objc func keyboardAppears(notification: Notification) {
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
bottomConstraint.constant = -1 * keyboardFrame.height
view.loadViewIfNeeded()
parentView.scrollUp()
}
}
func scrollUp() {
DispatchQueue.main.async {
self.entrySpace.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .top, animated: true)
}
}
UPDATE:
The following works after a letter is typed in the field (I want it to work right when the keyboard comes up)
NOTE: this is the UITableViewCell class because the cell is the last item in the UITableView
import UIKit
class EntryButtonCell: UITableViewCell {
//the textView for new entries
var entryCell = UITextView()
//Reference to the parent table
var parentTable = UITableView()
//Reference to the parent view (the one that holds the table view)
var parentView = ParentVC()
var bottomConstraint = NSLayoutConstraint()
//Initialization
override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
super.init(style: style, reuseIdentifier: reuseIdentifier)
//set this cell as the delegate for the entry textView
entryCell.delegate = self
//deactivate interaction with the cell so the user can interact with the textView
contentView.isUserInteractionEnabled = false
//set up the textView
prepTextView()
//set the notification for the keyboard events
setKeyboardObservers()
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
//deinitialization
deinit {
//remove the keyboard observers
removeKeyboardObservers()
}
func prepTextView() {
//just did the constraints here
//removing to save space
}
func scrollToBottom() {
DispatchQueue.main.async { [weak self] in
guard let data = self?.parentView.data else { return }
let indexPath = IndexPath(row: data.count, section: 0)
self?.parentTable.scrollToRow(at: indexPath, at: .bottom, animated: true)
}
}
//set the keyboard notification
private func setKeyboardObservers() {
//add keyboardWillShowNotification
NotificationCenter.default.addObserver(self, selector: #selector(keyboardAppears(notification:)), name: UIResponder.keyboardWillShowNotification, object: nil)
//add keyboardWillHideNotification
NotificationCenter.default.addObserver(self, selector: #selector(keyboardDisappears(notification:)), name: UIResponder.keyboardWillHideNotification, object: nil)
}
//deactivate the keyboard notifications
private func removeKeyboardObservers() {
//deactivate keyboardWillShowNotification
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillShowNotification, object: nil)
//deactivate keyboardWillHideNotification
NotificationCenter.default.removeObserver(self, name: UIResponder.keyboardWillHideNotification, object: nil)
}
//run when keyboard shows
@objc func keyboardAppears(notification: Notification) {
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect {
scrollToBottom()
bottomConstraint.constant = -1 * keyboardFrame.height
parentTable.layoutSubviews()
parentView.loadViewIfNeeded()
}
}
@objc func keyboardDisappears(notification: Notification) {
tableBottomConstraint.constant = -100.0
parentView.loadViewIfNeeded()
}
//Took out a few of the textView methods to save space
}