Dynamically Reconfigure Visible Title of an IB-based UIViewController before it is Visible

Howdy,

I have a storyboard-based view controller which I manually load into memory (i.e. no segues) and push into a navigation stack. For this view controller, I would like to dynamically update the title prior to presentation based on some runtime-state.

My initial assumption was that this could be done simply by updating navigationItem.title sometime before viewDidAppear(:). But this procedure is not behaiving quite as I expected. It seems that no matter where I set navigationItem.title, the rendered title is only updated after the view controller is fully pushed. Meaning that the user is able to see the title is changing from its default value as defined in the storyboard to the dynamically generated one. This is not the behavior I want.

What is the easiest/correct way to force an update to the visible title before the view controller is presented to the user? Is this even possible?

Thanks, smkuehnhold

Replies

Where did you set the title ? Could you show the code, including the code where you push the VC into navigation stack ?

@Claude31

I always appreciate to see your replies on this forum :)

For brevity, I hope you don't mind that I share a smaller example instead. Also, sorry for not replying as a comment. I could not fit an example.

protocol StoryboardBased: UIViewController {
  // instantiates a view controller from a storyboard
  // default impl based on UIStoryBoard(name:bundle:).instantiateViewController(withIdentifier:)
  func makeFromStoryboard() -> Self
}

class ViewController: UIViewController, StoryboardBased {
  required init?(coder: NSCoder) {
     super.init(coder: coder)
     _init()
  }

  override init(nibName nibNameOrNIl: String?, bundleName bundleNameOrNil: String?) {
     super.init(nibName: nibNameOrNIl, bundleName: bundleNameOrNil)
     _init()
  }

  private func _init() {
     // init is the earliest time you can update the title correct?
     // also doesn't work if I set in viewDidLoad(:) for reference
     // or if I set directly from outside prior to instance being pushed
     navigationItem.title = makeTitleFromDynamicData() // makeTitleFromDynamicData returns a (non-optional) String
  }
}

// Parent is in Navigation Stack
class ParentViewController: UIViewController {
   @IBAction func buttonTouchUpInside(_ sender: Any?) {
      // push a view controller in response to the user pressing a button
      navigationController.pushViewController(
        ViewController.makeFromStoryboard() // instantiate Storyboard-based ViewController,
        animated: true
      )
   }
}

Thanks, smkuehnhold

  • Did you try and do it in viewDidLoad ?

  • Yes. I observed the same behavior.

  • Scratch that.

    The issue is that my procedure to retrieve the dynamic title is a bit more complex than I let on and relies on an combine publisher that is recieved on DispatchQueue.main.

    I made an incorrect assumption that an event would fire off immediately once a subscription was made, which is where I got the idea that I had tried viewDidLoad(:).

    Thankfully this is an easy fix :)

Add a Comment