Search code examples
swiftswitch-statementuisegmentedcontrol

Using a UISegmentedControl like a UISwitch


Is it possible to use a UISegmentedControl with 3 segments as if it was a three-way UISwitch? I tried to use one as a currency selector in the settings section of my app with no luck, it keeps reseting to the first segment when I switch views and that creates a big mess.

I proceeded like that:

IBAction func currencySelection(_ sender: Any) {
    switch segmentedControl.selectedSegmentIndex {
    case 0:
        WalletViewController.currencyUSD = true
        WalletViewController.currencyEUR = false
        WalletViewController.currencyGBP = false
        MainViewController().refreshPrices()
        print(0)
    case 1:
        WalletViewController.currencyUSD = false
        WalletViewController.currencyEUR = true
        WalletViewController.currencyGBP = false
        MainViewController().refreshPrices()
        print(1)
    case 2:
        WalletViewController.currencyUSD = false
        WalletViewController.currencyEUR = false
        WalletViewController.currencyGBP = true
        MainViewController().refreshPrices()
        print(2)
    default:
        break
    }
}

Solution

  • The UISegmentedControl is implemented in the SettingsViewController of the app to choose between currencies to display in the MainViewController.

    (Taken from a comment in @pacification's answer.)

    This was the missing piece I was looking for. It provides a lot of context.

    TL;DR;

    Yes, you can use a three segment UISegmentedControl as a three-way switch. The only real requirement is that you can have only one value or state selected.

    But I wasn't grasping why your code referred to two view controllers and some of switching views resulting in resetting the segment. One very good way to do what you want is to:

    • Have MainViewController present SettingsViewController. Presenting it modally means the user is only doing one thing at a time. When they are making setting changes, you do not want them adding new currency values.

    • Create a delegate protocol in SettingsViewController and make MainViewController conform to it. This tightly-couples changes made to the settings to the view controller interested in what those changes are.

    Here's a template for what I'm talking about:

    SettingsViewController:

    protocol SettingsVCDelegate {
        func currencyChanged(sender: SettingsViewController)
    }
    class SettingsViewController : UIViewController {
    
        var delegate:SettingsVCDelegate! = nil
        var currency:Int = 0    
        @IBAction func valueChanged(_ sender: UISegmentedControl) {
            currency = sender.selectSegmentIndex
            delegate.currencyChanged(sender:self)
        }
    }
    

    MainViewController:

    class MainViewController: UIViewController, SettingsVCDelegate {
        var currency:Int = 0
        let settingsVC = SettingsViewController()
        override func viewDidLoad() {
            super.viewDidLoad()
            settingsVC.delegate = self
        }
        func presentSettings() {
            present(settingsVC, animated: true, completion: nil)
        }
        func currencyChanged(sender:SettingsViewController) {
            currency = sender.currency
        }
    }
    

    You can also create an enum of type Int to make your code more readable, naming each value as currencyUSD, currencyEUR, and currencyGBP. I'll leave that to you as a learning exercise.