如何在视图控制器之间传递数据 - 不起作用

Posted

技术标签:

【中文标题】如何在视图控制器之间传递数据 - 不起作用【英文标题】:How to pass data between view controllers - not working 【发布时间】:2019-01-20 21:24:34 【问题描述】:

我试图将玩家分数从 VC1 传递到显示所有玩家当前分数的视图 (4)。显示视图位于单独的视图控制器上,而不是定义和存储玩家分数的位置。

我已经完成了准备(segue)并且能够将其他变量传递给显示 VC(ThirdViewController)。但是当我尝试将玩家分数分配给 uilabel.text 时,它告诉我我已经打开了一个 nil 值

我什至尝试将标签文本设置为静态字符串,但仍然得到 nil 错误。

class ViewController: UIViewController 

var name = String()

var player1Score = 1
var player2Score = 2
var player3Score = 3
var player4Score = 4

//MARK: ********* IBOutlets **********
@IBOutlet weak var playerSegmentOutlet: UISegmentedControl!
@IBOutlet weak var diceSegmentOutlet: UISegmentedControl!
@IBOutlet weak var targetScoreSliderOutlet: UISlider!
@IBOutlet weak var matchTargetSwitchOutlet: UISwitch!
@IBOutlet weak var targetScoreLabel: UILabel!


override func viewDidLoad() 
    super.viewDidLoad()




override func prepare(for segue: UIStoryboardSegue, sender: Any?) 

    if let VC = segue.destination as? SecondViewController 

        VC.player1CurrentScore = player1Score
        VC.player2CurrentScore = player2Score
        VC.player3CurrentScore = player3Score
        VC.player4CurrentScore = player4Score
    

第二个视图控制器

class SecondViewController: UIViewController 

@IBOutlet weak var CurrentRoundScoreLabel: UILabel!

@IBOutlet weak var CurrentPlayerScoreLabel: UILabel!

var player1CurrentScore = 1
var player2CurrentScore = 1
var player3CurrentScore = 1
var player4CurrentScore = 1


override func viewDidLoad() 
    super.viewDidLoad()



override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let VC = segue.destination as? ThirdViewController 

        VC.player1ScoreLabel.text = String(player1CurrentScore)
        VC.player2ScoreLabel.text = String(player2CurrentScore)
        VC.player3ScoreLabel.text = String(player3CurrentScore)
        VC.player4ScoreLabel.text = String(player4CurrentScore)

    

第三视图控制器

class ThirdViewController: UIViewController 

@IBOutlet var player1ScoreLabel: UILabel!
@IBOutlet var player2ScoreLabel: UILabel!
@IBOutlet var player3ScoreLabel: UILabel!
@IBOutlet var player4ScoreLabel: UILabel!

override func viewDidLoad() 
    super.viewDidLoad()

无论我尝试用 UILabel.text 做什么,它都会显示为 nil

我非常沮丧,我确定我因为沮丧而错过了一些简单的事情,请有人帮助我。

【问题讨论】:

您永远不应该从 prepare 分配 destVC IBOutlet 的内容:因为 IBOutlet 还不存在,所以这不起作用。您需要设置一些 destVC 属性(通常在 destVC 中声明为可选);然后,在 destVC 的 viewDidLoad 中,使用这些属性来设置 IBOutlets(标签或其他)。 【参考方案1】:

这是一种低效的方法,因为您要通过 3 个不同的对象传递数据。但是,继续使用这种方法,问题是标签尚未在内部创建

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let VC = segue.destination as? ThirdViewController 

        VC.player1ScoreLabel.text = String(player1CurrentScore)
        VC.player2ScoreLabel.text = String(player2CurrentScore)
        VC.player3ScoreLabel.text = String(player3CurrentScore)
        VC.player4ScoreLabel.text = String(player4CurrentScore)

    

看,标签尚未创建。因此,您在未初始化的UILabel 上设置text。因此,您需要为ThirdViewController 中的标签创建变量。

第三视图控制器

class ThirdViewController: UIViewController 

    @IBOutlet var player1ScoreLabel: UILabel!
    @IBOutlet var player2ScoreLabel: UILabel!
    @IBOutlet var player3ScoreLabel: UILabel!
    @IBOutlet var player4ScoreLabel: UILabel!

    var score0:Int!
    var score1:Int!
    var score2:Int!
    var score3:Int!

    override func viewDidLoad() 
        super.viewDidLoad()
        self.player1ScoreLabel.text = String(score0)
        self.player2ScoreLabel.text = String(score1)
        self.player3ScoreLabel.text = String(score2)
        self.player4ScoreLabel.text = String(score3)
    

并在 SecondViewController 中更改 segue

override func prepare(for segue: UIStoryboardSegue, sender: Any?) 
    if let VC = segue.destination as? ThirdViewController 

        VC.score0 = player1CurrentScore
        VC.score1 = player2CurrentScore
        VC.score2 = player3CurrentScore
        VC.score3 = player4CurrentScore

    


另一种方式:

让我们创建一个名为Game 的单例。在此范围内(假设您只有 4 名玩家),我们可以创建 4 名玩家,他们永远不会改变。这允许我们在一个位置创建玩家实例并在必要时调用它们。

注意:单例很容易被滥用。

https://cocoacasts.com/what-is-a-singleton-and-how-to-create-one-in-swift https://cocoacasts.com/are-singletons-bad/

class Game 

    static var score0:Int = 0
    static var score1:Int = 0
    static var score2:Int = 0
    static var score2:Int = 0

        

然后,您可以在代码中的任何位置访问 Game.score0、Game.score1。

注意:

我会提醒您非常小心地使用单例。您不希望所有内容都具有公共访问权限。您需要确定这是否对您有好处。干杯。

【讨论】:

效果很好,非常感谢我正要拔头发:),我没有多余的了。 你提到效率低下,你将如何实现它。 当然可以。给我一些时间,这样你就可以继续工作了:P 好了!有点效率:P

以上是关于如何在视图控制器之间传递数据 - 不起作用的主要内容,如果未能解决你的问题,请参考以下文章

为什么这个代码在控制器之间传递数据不起作用?

视图控制器之间的导航不起作用

IOS Segue 在自定义标签栏中不起作用

从 Unwind segue 触发时,Push segue 不起作用

视图控制器和 UIView 之间的简单委托不起作用

在视图控制器之间传递数据 - Storyboards segues