Ios – Weird uitableview behaviour in iOS11. Cells scroll up with navigation push animation

animationiosuinavigationcontrolleruitableview

I have recently migrated some code to new iOS 11 beta 5 SDK.

I now get a very confusing behaviour from UITableView. The tableview itself is not that fancy. I have custom cells but in most part it is just for their height.

When I push my view controller with tableview I get an additional animation where cells "scroll up" (or possibly the whole tableview frame is changed) and down along push/pop navigation animation. Please see gif:

wavy tableview

I manually create tableview in loadView method and setup auto layout constraints to be equal to leading, trailing, top, bottom of tableview's superview. The superview is root view of view controller.

View controller pushing code is very much standard: self.navigationController?.pushViewController(notifVC, animated: true)

The same code provides normal behaviour on iOS 10.

Could you please point me into direction of what is wrong?

EDIT: I have made a very simple tableview controller and I can reproduce the same behavior there. Code:

class VerySimpleTableViewController : UITableViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        self.tableView.register(UITableViewCell.self, forCellReuseIdentifier: "Cell")
    }


    override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
    }

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


    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)

        cell.textLabel?.text = String(indexPath.row)
        cell.accessoryType = .disclosureIndicator

        return cell
    }


    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        tableView.deselectRow(at: indexPath, animated: true)

        let vc = VerySimpleTableViewController.init(style: .grouped)

        self.navigationController?.pushViewController(vc, animated: true)
    }
}

EDIT 2: I was able to narrow issue down to my customisation of UINavigationBar. I have a customisation like this:

rootNavController.navigationBar.setBackgroundImage(createFilledImage(withColor: .white, size: 1), for: .default)

where createFilledImage creates square image with given size and color.

If I comment out this line I get back normal behaviour.

I would appreciate any thoughts on this matter.

Best Answer

This is due to UIScrollView's (UITableView is a subclass of UIScrollview) new contentInsetAdjustmentBehavior property, which is set to .automatic by default.

You can override this behavior with the following snippet in the viewDidLoad of any affected controllers:

    tableView.contentInsetAdjustmentBehavior = .never

https://developer.apple.com/documentation/uikit/uiscrollview/2902261-contentinsetadjustmentbehavior

Related Topic