问题
I'm a new programmer and struggling with passing data between controllers, I am aware this question is asked in these forums but the uploaded code is much more complex compared to mine and i struggle to understand it so will upload my few lines i've written. I want to allow two players to type their names into my app and then click start game. when the start game button is pressed it takes them to a new view controller which has their names like this Joe Bloggs vs John Doe, I can achieve this IF i make my variables global but my understanding is this is bad practice so when i try and write the same code keeping the variables inside the View Controller it passes nil each time and i'm unsure what i have done wrong? Here is my few lines of code that i hope someone can answer what i'm doing wrong?
ViewController:
import UIKit
class ViewController: UIViewController {
var playerOneName: String!
var playerTwoName: String!
@IBOutlet weak var playerOneTextField: UITextField!
@IBOutlet weak var playerTwoTextField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
@IBAction func startGameButton(_ sender: Any) {
playerOneName = playerOneTextField.text!
playerTwoName = playerTwoTextField.text!
}
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let destinationVC = segue.destination as! GameViewController
destinationVC.playerOne.text = playerOneName
destinationVC.playerTwo.text = playerTwoName
}
}
}
GameViewController:
import UIKit
class GameViewController: UIViewController {
@IBOutlet weak var playerOne: UILabel!
@IBOutlet weak var playerTwo: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
}
回答1:
You can't set properties of @IBOutlets
before you controller is initialized.
You need to store values like String!
in second view controller. And init @IBOutlets
with them in viewDidLoad
method for example.
Change GameViewController
code to this:
import UIKit
class GameViewController: UIViewController {
@IBOutlet weak var playerOne: UILabel!
var playerOneName: String!
@IBOutlet weak var playerTwo: UILabel!
var playerTwoName: String!
override func viewDidLoad() {
super.viewDidLoad()
playerOne.text = playerOneName
playerTwo.text = playerTextName
// Do any additional setup after loading the view.
}
}
And prepare
in ViewController
:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let destinationVC = segue.destination as! GameViewController
destinationVC.playerOneName = playerOneName
destinationVC.playerTwoName = playerTwoName
}
}
Hope it helps
回答2:
You shouldn't set the label's text directly from another view controller, but create variables in GameViewController
to store the label text, change those variables in the segue and then change the label in your destination controller's viewDidLoad
method. See below code.
class GameViewController: UIViewController {
@IBOutlet weak var playerOne: UILabel!
@IBOutlet weak var playerTwo: UILabel!
var playerOneName:String?
var playerTwoName:String?
override func viewDidLoad() {
super.viewDidLoad()
playerOne.text = playerOneName
playerTwo.text = playerTwoName
// Do any additional setup after loading the view.
}
}
And in ViewController:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
if segue.identifier == "segue" {
let destinationVC = segue.destination as! GameViewController
destinationVC.playerOneName = playerOneName
destinationVC.playerTwoName = playerTwoName
}
}
回答3:
Your outlets don't get initialized until your controller's view is loaded. However, the segue happens before that.
The best solution is to put a couple of string properties into GameViewController
and use those to receive the data from your first controller. Then, update your label text in viewDidLoad
.
来源:https://stackoverflow.com/questions/44676205/passing-data-between-view-controllers-produces-nil