I have a tableview that I've initialized with 4 constraints in the viewDidLoad() method. I wanted to programmatically change the bottomAnchor later in the code so I saved it as a variable bottomAnchor
I then have another variable keyboardBottomAnchor
for the changed constraint
These are the initial constraints:
tableView.translatesAutoresizingMaskIntoConstraints = false
tableView.topAnchor.constraint(equalTo: self.view.safeAreaLayoutGuide.topAnchor, constant: 50).isActive = true
tableView.leadingAnchor.constraint(equalTo: self.view.leadingAnchor).isActive = true
tableView.trailingAnchor.constraint(equalTo: self.view.trailingAnchor).isActive = true
bottomAnchor = tableViewe.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: (-1) * card.cardHandleAreaHeight + -20)
bottomAnchor.isActive = true
Basically, I wanted the table view to go up when the keyboard open and back down when the keyboard closes. Here's how that looks:
@objc func keyboardAppears(notification: Notification) {
let userInfo = notification.userInfo
keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
//this is the original constraint
self.bottomConstraint.isActive = false
//Here I make a new variable to save the new constraint
keyboardBottomConstraint = tableView.bottomAnchor.constraint(equalTo: self.view.bottomAnchor, constant: -1 * keyboardFrame.height)
keyboardBottomConstraint.isActive = true
}
@objc func keyboardDisappears(notification: Notification) {
NSLayoutConstraint.deactivate([keyboardBottomConstraint])
bottomConstraint.isActive = true
}
The keyboardAppears
method is working (the table view goes up when the keyboard shows) but the keyboardDisappears
method is giving me a Unable to simultaneously satisfy constraints
error (aka it is saying that both bottomConstraint
and keyboardBottomConstraint
are active)
Any thoughts as to why this is happening?
UPDATE:
I used the .constant
below (this works but only the first time I open up the keyboard)
@objc func keyboardAppears(notification: Notification) {
let userInfo = notification.userInfo
var keyboardFrame = userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as! CGRect
bottomConstraint.constant = -1 * keyboardFrame.height
tableView.scrollUp()
}
@objc func keyboardDisappears(notification: Notification) {
returnOriginalConstraint()
}
func returnOriginalConstraint() {
bottomAnchor.constant = (-1) * buttonCard.cardHandleAreaHeight + -20
}
//scrolling method
func scrollUp() {
DispatchQueue.main.async {
self.entrySpace.scrollToRow(at: IndexPath(row: self.data.count - 1, section: 0), at: .top, animated: true)
}
}
Do not deactivate the constraint, just change its constant value.
I have written the code below and tested it, customize it as you like, will work perfectly with you!
import UIKit
class ViewController: UIViewController
{
// MARK: Properties
var tableView: UITableView!
var tableBottomConstraint: NSLayoutConstraint!
// MARK: View Controller Life Cycle
override func viewDidLoad()
{
super.viewDidLoad()
addKeyboardObservers()
setupTableView()
}
deinit
{
removeKeyboardObservers()
}
// MARK: Methods
private func addKeyboardObservers()
{
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillShow(notification:)),
name: UIResponder.keyboardWillShowNotification,
object: nil)
NotificationCenter.default.addObserver(self,
selector: #selector(keyboardWillHide(notification:)),
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
private func removeKeyboardObservers()
{
NotificationCenter.default.removeObserver(self,
name: UIResponder.keyboardWillShowNotification,
object: nil)
NotificationCenter.default.removeObserver(self,
name: UIResponder.keyboardWillHideNotification,
object: nil)
}
private func setupTableView()
{
tableView = UITableView()
tableView.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(tableView)
tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor, constant: 0.0).isActive = true
tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor, constant: 0.0).isActive = true
tableView.topAnchor.constraint(equalTo: view.topAnchor, constant: 50.0).isActive = true
tableBottomConstraint = tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor, constant: -50.0)
tableBottomConstraint.isActive = true
}
// MARK: Keyboard Handling
@objc func keyboardWillShow(notification: Notification)
{
if let keyboardFrame = notification.userInfo?[UIResponder.keyboardFrameEndUserInfoKey] as? CGRect
{
tableBottomConstraint.constant = -1 * keyboardFrame.height
loadViewIfNeeded()
}
}
@objc func keyboardWillHide(notification: Notification)
{
tableBottomConstraint.constant = -50.0
loadViewIfNeeded()
}
}
Note: Do not forget to remove keyboard observers in
deinit