Search code examples
iosswiftuinavigationbaruisegmentedcontrol

Why does the selector of my segmented control in a navigation bar not work?


First issue:
I can switch between segments but the app does not recognize the switching and never runs the selector function.

Second issue:
The navigation bar title doesn't show.

screenshot

Here is the code:

class ViewController: UIViewController {

    let mySegmentControl: UISegmentedControl = {
        let sc = UISegmentedControl(items: ["First","Second","Third"])
        sc.translatesAutoresizingMaskIntoConstraints = false
        sc.addTarget(self, action: #selector(handleSegmentChange), for: .valueChanged)
        sc.selectedSegmentIndex = 0

        if #available(iOS 13.0, *) {
            sc.selectedSegmentTintColor = .red
        } else {
            // Fallback on earlier versions
            sc.tintColor = .red
        }
        return sc
    }()

    override func viewDidLoad() {
        super.viewDidLoad()
        view.backgroundColor = .white
        navigationController?.navigationBar.tintColor = .blue
        navigationController?.navigationBar.barTintColor = .yellow
        navigationItem.title = "My App"
        self.navigationItem.titleView = mySegmentControl
    }

    @objc func handleSegmentChange() {
        let chosedIndex = mySegmentControl.selectedSegmentIndex
        print(chosedIndex)
    }
}

Solution

  • Inside the closure where you're creating mySegmentConstrol, self does not refer to what you think it does. In this case, self refers to something that is of type (ViewController) -> () -> ViewController, which is definitely not what you want:

    Some weird type

    To refer to the current ViewController instance, declare mySegmentControl as a lazy var:

    lazy var mySegmentControl: UISegmentedControl = {
    

    This should get your segmented control selector firing properly.

    As for showing your navigation item's title, well... you can't really do that and show a custom view in the navigation bar's titleView. It's one or the other.