This builds on @pogos answer, making sure you don't get errors when navigating to another viewController, which needs the same button. I remove the button, if it exists, before adding it. And do it in viewWillAppear instead of viewDidLoad. Also, must take into account the safeArea for the navigationBar, otherwise this doesn't work in landscape. I added the constant parameter to that constraint for that.
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
configureNavigationBarButton()
}
private func configureNavigationBarButton() {
guard let navigationController else { return }
let tag = 1000
navigationController.navigationBar.subviews.first(where: { $0.tag == tag })?.removeFromSuperview()
let button = UIButton()
button.tag = tag
button.translatesAutoresizingMaskIntoConstraints = false
navigationController.navigationBar.addSubview(button)
NSLayoutConstraint.activate([
button.topAnchor.constraint(equalTo: navigationController.navigationBar.topAnchor),
button.bottomAnchor.constraint(equalTo: navigationController.navigationBar.bottomAnchor),
button.trailingAnchor.constraint(equalTo: navigationController.navigationBar.trailingAnchor, constant: -navigationController.navigationBar.safeAreaInsets.right),
button.widthAnchor.constraint(equalToConstant: 58)
])
button.addTarget(self, action: #selector(openMenu), for: .touchUpInside)
}