Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

iOS 11 prefersLargeTitles not displaying until scroll

I'm having issues with iOS 11's large titles when using a Table View Controller.

I have set prefersLargeTitles to true in the viewDidLoad:

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.navigationBar.prefersLargeTitles = true
}

When running my app the title appears as if prefersLargeTitles is set to small, but if I then scroll down, the large title appears.

I have 2 UIViewControllers, and they both display the large title correctly, bar the UITableViewController.

I have tried different combinations of setting prefersLargeTitles to true in the code and within the storyboard, where you can set Large Title to Automatic, Always or Never.

I can only find one other question on Stack Overflow which refers to this exact issue, but none of the answers seem to solve it.

Has anyone else who has run into this issue been able to solve it?

like image 980
Gian Avatar asked Mar 07 '23 03:03

Gian


2 Answers

After setting prefersLargeTitles, you can trigger the large titles to show by calling setContentOffset on your UITableView.

override func viewDidLoad() {
    super.viewDidLoad()

    navigationController?.navigationBar.prefersLargeTitles = true
    self.tableView.setContentOffset(CGPoint(x: 0, y: -1), animated: true)
}
like image 93
Gandalf458 Avatar answered Mar 15 '23 02:03

Gandalf458


Perhaps you are reloading the tableView prior to viewDidLoad? I observed the same behavior today. In my case, I had a didSet on a variable that was set before viewDidLoad that called tableView.reloadData.

I was able to fix this by adding a guard so the reloadData only happened when the variable wasn't previously nil, meaning the first time.

Here's my calling class for reference...

/// Master Controller in UISplitViewController
class MyMasterViewController: UIViewController {

  private let controller = MyTableViewController()

  override func viewDidLoad() {
    super.viewDidLoad()

    controller.instanceVariable = data
    showDetailViewController(navigationController, sender: self)
  }

...

  private func reloadDetail() {
    controller.instanceVariable = newData
  }
}

And here's the fix - added the guard statement below...

/// Detail Controller in UISplitViewController
class MyTableViewController: UITableViewController {

  var instanceVariable: MyData! {
    didSet {
      guard oldValue != nil else { return }
      tableView.reloadData()
    }
  }

  // UITableViewController Methods...
}

Hope this helps! If my example doesn't make sense, I'd suggest commenting out all references to tableView.reloadData and then only re-adding when sure they aren't getting called until after the tableView loads initially.

like image 42
Matthew Wakefield Avatar answered Mar 15 '23 02:03

Matthew Wakefield