I’m working on a controller that will allow a user to set the number of players they would like in a game. The view consists of some labels, a slider, and a button. The slider allows the user to select a value from 1-4 to select the number of players. One of those labels is set to x Player(s) Selected
where x is the slider’s value rounded to the nearest Int
. The button then sends the user to the game (another view) which is handled by a different View Controller (VC). I’m trying to send the number of players to the other VC but the value does not appear to be saved outside of the IBAction function.
As a possible fix, I’ve tried using an instance of GameViewController
in NumberOfPlayersViewController.swift
and updating the variable in setNumOfPlayers
, which also did not work. Am I just missing something or is updating a variable in an IBAction not possible?
// NumberOfPlayersViewController.swift
import UIKit
class NumberOfPlayersViewCOntroller: UIViewController {
// Default number of players
var numOfPlayers = 1
// UIObjects
<Label here>
<Slider here>
@IBAction private func setNumOfPlayers(_ sender: UISlider) -> Void {
// Get the number of players and update the label
numOfPlayers = Int(sender.value) // Originally float, rounds the value to the nearest Int
label.text = "(numOfPlayers) Player(s) Selected" // Updates label
print(numOfPlayers) // Prints the rounded value
}
func getNumberOfPlayers() -> Int {
return numOfPlayers // Only returns the default value of 1
// GameViewController.swift
class GameViewController:UIViewController {
let NumberOfPlayersVC = NumberOfPlayersViewController()
lazy var numOfPlayers = NumberOfPlayersVC.getNumberOfPlayers() // Lazy as `self` is not available
override func viewDidLoad() {
super.viewDidLoad()
print(numOfPlayers) // Prints 1
}
}
These views that these ViewControllers handle are connected via a Seque.
2
Answers
A solution to my problem was actually answered in this question: Passing variables between View Controllers using a segue, but I had missed it in my search. The solution involves using
performSegue
andprepare
in order to transfer data between views. The answer also includes what to change in order to use this method in Swift 3+.Your
GameViewController
creates an instance ofNumberOfPlayersViewController
when it’s created. In its viewDidLoad, you then fetch the value numOfPlayers. That lazy var will ask your NumberOfPlayersVC, once and only once, for the value ofgetNumberOfPlayers()
.If that instance of
NumberOfPlayersViewController
has never been displayed to the screen and had the user update its slider and tap its button, it will still return a value of 1.How do the 2 view controllers get displayed to the screen? When does the user get a chance to pick a value on your slider and tap the
setNumOfPlayers
button?I don’t see how that can happen between your
GameViewController
being initialized and its viewDidLoad method being invoked. That seems to be the problem. YourGameViewController
is initialized, it creates a new instance ofNumberOfPlayersViewCOntroller
, itsviewDidLoad
method fires, its lazy var callsgetNumberOfPlayers()
on theNumberOfPlayersViewCOntroller
, which returns 1 since that view controller hasn’t been displayed on the screen yet. The lazy var will now always have a 1 in it.