skip to Main Content

I’m working on an app that currently has 2 view controllers.
Within the second viewcontroller, (which I’m using for settings) I use a segement control in order to determine the game’s difficulty. The settings viewcontroller’s purpose is to make changes to the main viewcontroller labels.
The problem I’m having is that I can’t find a way to bring the selected index value of the segment control from the second viewcontroller to the main one.

here’s the settings screen view controller:

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

    }   
 }

and the main:

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

3

Answers


  1. You can use the Delegate pattern or the Closure Callback pattern.
    like this:

    ** SettingsScreen:**

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

    ** MainScreen:**

        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)
        
        }
        
    }
    
    Login or Signup to reply.
  2. Try a different approach. Instead of trying to figure out the selected index in your main controller, you could directly update the labels of the main controller from the settings controller. You can use NSNotification to achieve this.

    In your main controller viewDidLoad:

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

    In settings controller in your UISegmentedControl’s value changed event:

    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)
    }
    
    Login or Signup to reply.
  3. Since you’re referring to a referencing a user specified SegmentedIndex based on some setting changes, you could utilise UserDefaults to store that index for later retrieval. This would be Simpler but it also depends on what you’re actually after.

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

    Then in your MainScreen code

      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
           }
       }
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search