Search code examples
swiftuinavigationcontrolleruisegmentedcontrol

Trying to handle segmented control switch inside of navigation bar title view


I created a segmented control using

private let updateSwitch: UISegmentedControl = {
    let sc = UISegmentedControl(items: ["Sign In", "Sign Out"])
    sc.anchor(width: 128, height: 32)
    sc.selectedSegmentIndex = 0
    sc.tintColor = .mainBlue
    sc.backgroundColor = .mainGray
    sc.addTarget(self, action: #selector(handleSegmentedControlSwitch(_:)), for: .valueChanged)
    return sc
}()

I then added updateSwitch to my navigation bar using

navigationItem.titleView = updateSwitch

The segmented control shows up completely fine but whenever I select either sign in or sign out, the selector code does not get executed

@objc func handleSegmentedControlSwitch(_ segmentedControl: UISegmentedControl) {
    switch(segmentedControl.selectedSegmentIndex) {
        case 0:
            print("Sign In")
        break
        case 1:
            print("Sign Out")
        break
        default:
        break
    }
}

Any idea on how I can fix this?

Attached is an image of the working segmented control

image of working segmented control


Solution

  • It's because of your UISegmentControl declaration.

    You have 2 ways:

    1. declare it as a lazy var:

    because Self in lazy var is valid.

        private lazy var updateSwitch: UISegmentedControl = {
         let sc = UISegmentedControl(items: ["Sign In", "Sign Out"])
         sc.anchor(width: 128, height: 32)
         sc.selectedSegmentIndex = 0
         sc.tintColor = .mainBlue
         sc.backgroundColor = .mainGray
         sc.addTarget(self, action: #selector(handleSegmentedControlSwitch(_:)), for: .valueChanged)
        return sc }()
    

    2. assign action in viewDidLoad

        override func viewDidLoad() {
        super.viewDidLoad()
        let segmented = self.updateSwitch
        segmented.addTarget(self, action: #selector(handleSegmentedControlSwitch(_:)), for: .valueChanged)
        navigationItem.titleView = segmented
    }