【问题标题】:Using a UISegmentedControl like a UISwitch像 UISwitch 一样使用 UISegmentedControl
【发布时间】:2023-04-05 23:57:02
【问题描述】:

是否可以像使用三路 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
    }
}

【问题讨论】:

  • 您可以将状态保存到 UserDefaults 并在每次查看 apper 时读取
  • (1) 当然可以。只要只有一个开关状态是可能的,就可以使用分段控件。 (2) 我的直觉说你做的事情不正确。但是很难根据发布的代码确切地说出什么。 refreshPrices 在做什么?为什么它是另一个视图控制器的一部分? “当我切换视图时” 是什么意思?我认为您正在重置分段控件的代码not 中的某处。 (3)如果你把分段控件当成三路开关,那么你贴的switch代码就不需要了。看看selectedSegmentIndex
  • 非常感谢@Masiama 我在segmentedControl.selectedSegmentIndex 上使用UserDefaults 成功保存了UISegmentedControl 状态。
  • @dfd refreshPrices 用于刷新MainViewController 上显示的价格值和NumberFormatter,具体取决于UISegmentedControl 的货币选择。我敢肯定我没有做任何事情,因为我能做到的那么简单,哈哈。我使用switch-case 逻辑来获取变量,然后当我需要加载任何一个或货币时,我可以在项目的任何地方使用。也许我可以为此使用 segmentedControl.selectedSegmentIndex 值?
  • 我刚刚发布了一个答案。您对另一个答案的评论阐明了您正在尝试做的事情。在其中,我建议设置一个委托并展示设置 VC。

标签: swift switch-statement uisegmentedcontrol


【解决方案1】:

UISegmentedControlSettingsViewController 的应用程序可以在货币之间进行选择 显示在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)
    }
}

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

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

【讨论】:

    【解决方案2】:

    当我切换视图时它会一直重置到第一段

    是的,是的。为避免这种情况,您应该在每次使用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。

    【讨论】:

    • 所以我不需要我的WalletViewController.currency 变量,只需在switch 语句中设置segmentedControl.selectedSegmentIndex
    • 我的意思是如果你选择了currencyEUR(第二个),弹出你的控制器并再次用UISegmentedControl打开控制器,它总是切换到第一个值(初始状态)。在这种情况下,您需要手动设置selectedSegmentIndex
    • 很抱歉,您能给我看一个代码示例吗?
    • 顺便说一句,我不会使用UISegmentedControl 弹出任何视图。我只是用它作为三路UISwitch在函数中加载不同的数据。
    • @Martin33000,UISegmentedControl 何时变回初始值?
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-05-15
    • 1970-01-01
    • 2015-10-08
    • 2015-01-23
    • 1970-01-01
    相关资源
    最近更新 更多