Passing data between view controllers produces nil [duplicate]

被刻印的时光 ゝ 提交于 2021-02-10 18:18:56

问题


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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!