Để tạo UIBarButtonItem và gán action tại runtime (không dùng Storyboard), thực hiện các bước sau trong viewWillLayoutSubviews hoặc viewDidLoad.
Code hoàn chỉnh
class ViewController: UIViewController {
override func viewWillLayoutSubviews() {
super.viewWillLayoutSubviews()
// 1. Tạo bar button
let barButton = UIBarButtonItem()
barButton.title = "Custom"
// Hoặc dùng system item: UIBarButtonItem(barButtonSystemItem: .done, target: self, action: #selector(doneTapped))
// 2. Gán target & action
barButton.target = self
barButton.action = #selector(barButtonTapped)
// 3. Thêm vào navigation item (left hoặc right)
navigationItem.setLeftBarButton(barButton, animated: true)
// navigationItem.setRightBarButton(barButton, animated: true)
}
@objc func barButtonTapped() {
print("Bar button pressed")
// Xử lý logic ở đây
}
}
Kết quả
Nút xuất hiện trên Navigation Bar:

Console in ra khi tap nhiều lần:

Các kiểu UIBarButtonItem phổ biến
// Title text
UIBarButtonItem(title: "Done", style: .done, target: self, action: #selector(done))
// System item (icon chuẩn iOS)
UIBarButtonItem(barButtonSystemItem: .camera, target: self, action: #selector(openCamera))
UIBarButtonItem(barButtonSystemItem: .add, target: self, action: #selector(add))
UIBarButtonItem(barButtonSystemItem: .save, target: self, action: #selector(save))
UIBarButtonItem(barButtonSystemItem: .cancel, target: self, action: #selector(cancel))
UIBarButtonItem(barButtonSystemItem: .flexibleSpace, target: nil, action: nil) // Khoảng trống co giãn
UIBarButtonItem(barButtonSystemItem: .fixedSpace, target: nil, action: nil) // Khoảng trống cố định
// Custom view (UIImageView, UIButton, UILabel...)
let customBtn = UIButton(type: .custom)
customBtn.setImage(UIImage(named: "icon"), for: .normal)
customBtn.addTarget(self, action: #selector(customTap), for: .touchUpInside)
UIBarButtonItem(customView: customBtn)
// Image custom
UIBarButtonItem(image: UIImage(named: "icon"), style: .plain, target: self, action: #selector(tap))
Lưu ý
- Phải gán
targettrước hoặc cùng lúc vớiaction. - Selector phải có
@objcvà tham số(_ sender: Any)hoặc(). - Nếu dùng
navigationItem.leftBarButtonItem = barButton(property), animation không hoạt động – dùngsetLeftBarButton(_:animated:). - Để ẩn:
navigationItem.leftBarButtonItem = nil.