【问题标题】:accessing segmented control selected index from another viewcontroller从另一个视图控制器访问分段控件选定的索引
【发布时间】:2021-10-12 16:14:47
【问题描述】:

我正在开发一个当前有 2 个视图控制器的应用程序。 在第二个视图控制器(我用于设置)中,我使用分段控件来确定游戏的难度。设置视图控制器的目的是更改主视图控制器标签。 我遇到的问题是我找不到将段控件的选定索引值从第二个视图控制器带到主视图控制器的方法。

这是设置屏幕视图控制器:

    public class SettingsScreen: UIViewController {
    
    @IBOutlet weak var levelPick: UISegmentedControl! // need to use this
    @IBOutlet weak var operationPick: UISegmentedControl!
    
    public override func viewDidLoad() {
        super.viewDidLoad()

    }   
 }

还有主要的:

    class MainScreen: UIViewController {
       
       @IBOutlet weak var displayText: UILabel!

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

       }
       
       
      // how it should work:

      func setLevel() {
           switch SettingsScreen().levelPick.selectedSegmentIndex {
           // easy
           case 0:
               displaytext.text = "test1"
           // medium
           case 1:
               displaytext.text = "test2"
           // hard
           case 2:
               displaytext.text = "test3"
           default:
               break
           }

       }

       @IBAction func Roll(_ sender: UIButton) {
           setLevel()
       } 
   }

【问题讨论】:

  • 如何将更改更新到 UserDefault 变量并访问它。
  • @myjunk 究竟如何?我的帖子的重点是我找不到从第二个视图控制器访问变量的正确方法
  • 这实际上取决于你的应用程序如何构建,有很多方法可以将变量传递给第二个 VC,有些比大多数更复杂,有些很简单。从您的代码示例中,也许可以使用一些简单的东西,我发布了一个您可以使用的示例答案。

标签: swift xcode uikit uilabel uisegmentedcontrol


【解决方案1】:

由于您引用的是基于某些设置更改指定的用户 SegmentedIndex,因此您可以利用 UserDefaults 存储该索引以供以后检索。这会更简单,但也取决于您实际追求的目标。

public class SettingsScreen: UIViewController {

@IBOutlet weak var levelPick: UISegmentedControl! // need to use this
@IBOutlet weak var operationPick: UISegmentedControl!

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

}   


  @IBAction func levelPickPressed(_ sender: UISegmentedControl) {
    switch levelPick.selectedSegmentIndex {
      case 0:        // Easy
        defaults.set(0, forKey: "levelPick_Level")
        
      case 1:        // Med
        defaults.set(1, forKey: "levelPick_Level")
        
      case 2:       // Hard
        defaults.set(2, forKey: "levelPick_Level")

      default:
        break
      }
   }
}

然后在你的 MainScreen 代码中

  func setLevel() {
       levelPick = UserDefaults.standard.integer(forKey: "levelPick_Level")
       switch levelPick {
       // easy
       case 0:
           displaytext.text = "test1"
       // medium
       case 1:
           displaytext.text = "test2"
       // hard
       case 2:
           displaytext.text = "test3"
       default:
           break
       }
   }

【讨论】:

  • 这行是什么意思 - defaults.set(0, forKey: "levelPick_Level")?我已将其更改为 levelPick.setValue(0, forKey: "levelPick_Level") 并且它可以工作,但是一旦我选择不同的索引就会崩溃
  • 你为什么不使用defaults.set(0, forKey: "levelPick_Level"),它不起作用吗?这是设置userDefaults 来存储您选择的用户selectedSegmentIndex 我希望您至少用谷歌搜索它(learnappmaking.com/…)顺便说一句-setValue(_:forKey) 用于键:值字典(developer.apple.com/documentation/objectivec/nsobject/…
  • 您好,非常感谢您的帮助。我终于设法做对了。最后,我使用 Segues 将变量从一个视图控制器传递到另一个。
【解决方案2】:

尝试不同的方法。您可以直接从设置控制器更新主控制器的标签,而不是试图找出主控制器中的选定索引。您可以使用 NSNotification 来实现这一点。

在你的主控制器 viewDidLoad:

NotificationCenter.default.addObserver(forName: NSNotification.Name("notification1"), object: nil, queue: nil) { _ in
    self.myFunction // basically update labels and call your self.present() here
}

在 UISegmentedControl 的值更改事件的设置控制器中:

override func viewDidLoad() {
    super.viewDidLoad()
    mySegmentedControl.addTarget(self, action: #selector(function), for: .valueChanged)
}

@objc func function() {
    NotificationCenter.default.post(name: NSNotification.Name("notification1"), object: nil)
}

【讨论】:

  • 我想用主视图控制器内的滚动按钮更新标签。我怎样才能做到这一点?还有 self.present() 是什么意思?
【解决方案3】:

您可以使用委托模式或闭包回调模式。 像这样:

** 设置屏幕:**

class SettingsViewController: UIViewController {

    var segmentIndex: Int = 0
    
    var closure: ((_ segmentIndex: Int) -> ())?
    
    @IBOutlet weak var levelPick: UISegmentedControl!
    
    override func viewDidLoad() {
        super.viewDidLoad()

        self.levelPick.selectedSegmentIndex = self.segmentIndex

    }
    
    @IBAction func levelPickAction(_ sender: Any) {
        
        guard let closure = self.closure else {
            return
        }
        closure(levelPick.selectedSegmentIndex)
    }
    
}

** 主屏幕:**

    class MainViewController: UIViewController {

    var segmentIndex: Int = 0

    @IBOutlet weak var displayText: UILabel!
    
    override func viewDidLoad() {
        super.viewDidLoad()

    }
    
    @IBAction func Roll(_ sender: Any) {
        
        let vc = (UIStoryboard(name: "Main", bundle: nil).instantiateViewController(withIdentifier: "SettingsViewController") as! SettingsViewController)
        vc.segmentIndex = segmentIndex
        vc.closure = { [weak self] segmentIndex in
            self!.segmentIndex = segmentIndex
            switch segmentIndex {
            // easy
            case 0:
                self!.displayText.text = "test1"
            // medium
            case 1:
                self!.displayText.text = "test2"
            // hard
            case 2:
                self!.displayText.text = "test3"
            default:
               break
            }
        }
        self.present(vc, animated: true, completion: nil)
    
    }
    
}

【讨论】:

  • 嘿。好吧,它不再崩溃,但也没有改变任何东西,就像代码不存在一样。此外,每次我切换到主屏幕时,从设置屏幕中选择的索引都会重置
  • @Roei 你是对的。我在两个 ViewController 中都添加了一个 segmentIndex 变量。看看吧。
  • 还是不行,什么都没变。顺便说一句,我非常感谢您的帮助!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多