像 UISwitch 一样使用 UISegmentedControl

Using a UISegmentedControl like a UISwitch

是否可以像使用三路 UISwitch 一样使用具有 3 个分段的 UISegmentedControl?我尝试在我的应用程序的设置部分中使用一个作为货币选择器,但没有成功,当我切换视图时它一直重置到第一部分,这造成了一个大混乱。

我是这样进行的:

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
    }
}

it keeps reseting to the first segment when I switch views

是的,是的。为避免这种情况,每次使用 UISegmentedControl 加载视图时,都应将正确的开关值设置为 segmentedControl.selectedSegmentIndex

UPD

好的,MainViewController的行为可以类似于这样:

final class MainViewController: UIViewController {

    private var savedValue = 0

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    func openSettingsController() {
        let viewController = SettingsController.instantiate() // simplify code a bit. use the full controller initialization
        viewController.configure(value: savedValue, onValueChanged: { [unowned self] value in
            self.savedValue = value
        })
        navigationController?.pushViewController(viewController, animated: true)
    }

}

还有SettingsViewController

final class SettingsViewController: UIViewController {

    @IBOutlet weak var segmentedControl: UISegmentedControl!

    private var value: Int = 0

    var onValueChanged: ((Int) -> Void)?

    func configure(value: Int, onValueChanged: @escaping ((Int) -> Void)) {
        self.value = value
        self.onValueChanged = onValueChanged
    }

    override func viewDidLoad() {
        super.viewDidLoad()

        segmentedControl.selectedSegmentIndex = value
    }

    @IBAction func valueChanged(_ sender: UISegmentedControl) {
        onValueChanged?(sender.selectedSegmentIndex)
    }

}  

如果您从 SettingsViewController 移动,您应该保留您选择的值的主要想法。为此,您可以创建闭包

var onValueChanged: ((Int) -> Void)?

将选定的 UISegmentedControl 值传回 MainViewController。将来当您再次打开 SettingsViewController 时,您只需 configure() 这个值并将其设置为 UI.

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

(摘自@pacification 的回答中的评论。)

这就是我要找的丢失的部分。它提供了很多上下文。

TL;DR;

是的,您可以使用三段UISegmentedControl作为三路开关。唯一的真实要求是您只能选择一个值或状态。

但我不明白为什么您的代码引用了两个视图控制器和一些导致重置段的切换视图。做你想做的事情的一个很好的方法是:

  • MainViewController现在SettingsViewController。模态呈现意味着用户一次只做一件事。当他们进行设置更改时,您不希望他们添加新的货币值。

  • SettingsViewController中创建委托协议并使MainViewController符合它。这将对设置所做的更改紧密耦合到对这些更改感兴趣的视图控制器。

这是我所说的模板:

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)
    }
}

主视图控制器:

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
    }
}

您还可以创建类型为 Intenum 以使您的代码更具可读性,将每个值命名为 currencyUSDcurrencyEURcurrencyGBP.我会把它留给你作为学习练习。