Borys T
Borys T

Reputation: 239

Scroll view "disconnects" from navigation bar when swipe back is cancelled

First view controller has navigation bar hidden. Second has visible nav bar with large title. Transition forward is fine. Scroll view behaves as intended - navigation bar stretches while pulling down, and shrinks when pulling up. However when I use swipe back gesture and cancel it, scroll view "disconnects" from navigation bar and now it doesn't shrink or stretch.

enter image description here

Xcode 11.3, iOS 13.3

class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!

override func viewDidLoad() {
    super.viewDidLoad()        

    view.backgroundColor = .orange

    button.addTarget(self, action: #selector(tap), for: .touchUpInside)

    setupNavigationController()
}

func setupNavigationController() {
    if #available(iOS 13.0, *) {
        let coloredAppearance = UINavigationBarAppearance()
        coloredAppearance.configureWithOpaqueBackground()
        coloredAppearance.backgroundColor = .white
        coloredAppearance.titleTextAttributes = [.foregroundColor: UIColor.black]
        coloredAppearance.largeTitleTextAttributes = [.foregroundColor: UIColor.black, .font: UIFont.systemFont(ofSize: 26)]

        let coloredAppearance2 = UINavigationBarAppearance(barAppearance: coloredAppearance)

        coloredAppearance2.shadowColor = nil

        navigationController?.navigationBar.standardAppearance = coloredAppearance
        navigationController?.navigationBar.scrollEdgeAppearance = coloredAppearance2
    }

    navigationController?.navigationBar.prefersLargeTitles = true
}

@objc func tap() {
    navigationController?.pushViewController(DetailsViewController(), animated: true)
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    navigationController?.setNavigationBarHidden(true, animated: true)
}
}

Second view controller

class DetailsViewController: UIViewController, UITableViewDataSource {

override func viewDidLoad() {
    super.viewDidLoad()

    title = "Details"

    view.backgroundColor = .systemPink

    let tableView = UITableView(frame: .zero, style: .grouped)
    tableView.dataSource = self
    view.addSubview(tableView)
    tableView.translatesAutoresizingMaskIntoConstraints = false

    NSLayoutConstraint.activate([
        tableView.leadingAnchor.constraint(equalTo: view.leadingAnchor),
        tableView.trailingAnchor.constraint(equalTo: view.trailingAnchor),
        tableView.topAnchor.constraint(equalTo: view.topAnchor),
        tableView.bottomAnchor.constraint(equalTo: view.bottomAnchor),
    ])
}

override func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)

    navigationController?.setNavigationBarHidden(false, animated: true)
}

func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return 20
}

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell: UITableViewCell = {
        let identifier = "cell"
        guard let cell = tableView.dequeueReusableCell(withIdentifier: identifier) else {
            return UITableViewCell(style: UITableViewCell.CellStyle.default, reuseIdentifier: identifier)
        }
        return cell
    }()

    cell.textLabel?.text = "Row \(indexPath.row)"

    return cell
}
}

Upvotes: 3

Views: 431

Answers (1)

matt
matt

Reputation: 535306

It's a clear bug. Here's a workaround. To your table view controller, add this code:

override func viewDidAppear(_ animated: Bool) {
    super.viewDidAppear(animated)
    self.navigationController?.view.setNeedsLayout()
}

Upvotes: 2

Related Questions