Để thêm UINavigationBar thủ công bằng code (không dùng Storyboard Embed In Navigation Controller), thực hiện trong viewWillLayoutSubviews hoặc viewDidLoad.
Code cơ bản
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
let width = view.frame.width
let navBar = UINavigationBar(frame: CGRect(x: 0, y: 0, width: width, height: 44))
view.addSubview(navBar)
let navItem = UINavigationItem(title: "Navigation Bar")
let doneBtn = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped))
navItem.rightBarButtonItem = doneBtn
navBar.setItems([navItem], animated: false)
}
@objc func doneTapped() {
print("Done tapped")
}
Kết quả

Lưu ý quan trọng
- Navigation Bar thêm bằng code KHÔNG tự động quản lý push/pop view controller như
UINavigationController. - Chỉ là một View hiển thị title/buttons – cần tự handle navigation logic.
- Thường dùng khi: Không muốn full Navigation Controller, hoặc custom transition phức tạp.
- Safe Area: Trên iPhone X+ (notch), NavBar frame y=0 sẽ che status bar. Nên dùng
view.safeAreaLayoutGuide.topAnchor.
Cách đúng với Safe Area (iOS 11+)
let navBar = UINavigationBar()
navBar.translatesAutoresizingMaskIntoConstraints = false
view.addSubview(navBar)
NSLayoutConstraint.activate([
navBar.leadingAnchor.constraint(equalTo: view.leadingAnchor),
navBar.trailingAnchor.constraint(equalTo: view.trailingAnchor),
navBar.topAnchor.constraint(equalTo: view.safeAreaLayoutGuide.topAnchor),
navBar.heightAnchor.constraint(equalToConstant: 44)
])
let navItem = UINavigationItem(title: "Title")
navItem.rightBarButtonItem = UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(done))
navBar.setItems([navItem], animated: false)
Khuyến nghị
99% trường hợp nên dùng UINavigationController (Embed in Storyboard hoặc let nav = UINavigationController(rootViewController: vc)). Chỉ dùng UINavigationBar standalone khi có lý do đặc biệt.