I have the following example which shows the issue.
I basically want to show a UI similar to iMessage where a UITextView is present at the bottom for typing the message.
Once the keyboard is shown in the UITextView, upon scrolling the UITableView even slightly, the content goes under the navigation bar while the navigation bar stays transparent. It seems like a weird UI bug.
import UIKit
import SnapKit
let numberOfRows = 15
class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
@IBOutlet var myTableView: UITableView!
let textView = UITextView()
let bottomView = UIView()
override func viewDidLoad() {
super.viewDidLoad()
myTableView.keyboardDismissMode = .interactive
bottomView.backgroundColor = .darkGray
bottomView.addSubview(textView)
view.addSubview(bottomView)
bottomView.snp.makeConstraints { make in
make.left.right.bottom.equalToSuperview()
make.height.equalTo(100)
}
textView.backgroundColor = .black
textView.snp.makeConstraints { make in
make.edges.equalToSuperview().inset(10)
}
textView.text = "Type something.."
}
override var inputAccessoryView: UIView {
return bottomView
}
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat {
return UITableView.automaticDimension
}
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
return 200
}
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return numberOfRows
}
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "Cell")!
cell.textLabel?.text = "Row \(indexPath.row)"
cell.detailTextLabel?.text = "Tastes very close to Snickers chocolate bar. Only tried because of reviews. Would purchase again if price wasn’t so high, and available in Canada."
return cell
}
func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
navigationController?.pushViewController(UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "DetailVC"), animated: true)
}
}
Screenshot of the bug after scrolling even a tiny bit after keyboard is shown:

I experience the same behavior as you with this code. There is definitely something confusing the top safe area guide.
I solved the problem by abandoning this
inputAccessoryViewpattern altogether. I justkeyboardLayoutGuide.topAnchor.Having done that, you enjoy the “keep the text view right above the keyboard” functionality, without this idiosyncratic navigation bar behavior/bug.
This approach also enjoys the automatic adjustment of the tableview scroll area so that you can still scroll to the bottom even if the keyboard is presented. It also is a zero-code solution.
FWIW, if doing this in IB, you may have to select the main view and explicitly enable the keyboard layout guides:
In iOS versions prior to iOS 15, we used to have to add keyboard observers. So, we would add an
@IBOutletfor the bottom constraint to the superview and then manually change that bottom constraint (animating it alongside the presentation and dismissal of the keyboard). E.g., I have done something along those lines in my pre iOS 15 projects:With:
And that uses this
UIViewControllerextension:This is all a bit cumbersome, which is why the iOS 15 keyboard layout guides were so welcomed. But in earlier iOS versions, we would observe the presentation and dismissal of the keyboard manually.