为什么在不同的视图控制器上 segue 后分数不显示?

Why isn't the score showing up after segue on different view controller?

我创建了一个测验应用程序,它会跟踪用户的分数,直到用户完成为止。有一个 if 语句 - 当它到达测验的结尾时,会弹出一个结果视图控制器。我的问题是我想在 resultsViewContoller 上获得相同的分数值。我已经通过 segue 连接它并且标识符已经放置。 应用程序运行,但是当我结束时,segue 打开了页面,但分数没有改变?

我该如何解决这个问题?

用户完成了应用程序。我调用了 segue 方法,屏幕出现了。

结果视图控制器

import UIKit

class ResultsViewController: UIViewController {
    
    var fruitness = Fruitness()
    
    @IBOutlet weak var finalScoreLabel: UILabel!
    
    var finalScore: String!
    
    override func prepare(for: UIStoryboardSegue, sender: Any?) {
        func viewWillAppear(_ animated: Bool) {
            
            finalScoreLabel.text = finalScore
            
            
            if finalScore != nil {
                finalScoreLabel.text = "FINALSCORE:\(String(describing: Int(finalScore!)))"
                
            }
        }
    }
}

游戏视图控制器


import UIKit

class GameViewController: UIViewController {
    
    @IBOutlet weak var progressBar: UIProgressView!
    
    @IBOutlet private weak var fruitLabel: UILabel!
    
    @IBOutlet private weak var scoreLabel: UILabel!
    
    @IBOutlet weak var replayGame: UIButton!
    
    
    @IBOutlet weak var optionButton0: UIButton!
    @IBOutlet weak var optionButton1: UIButton!
    @IBOutlet weak var optionButton2: UIButton!
    @IBOutlet weak var optionButton3: UIButton!
    @IBOutlet weak var optionButton4: UIButton!
    @IBOutlet weak var optionButton5: UIButton!
    @IBOutlet weak var optionButton6: UIButton!
    @IBOutlet weak var optionButton7: UIButton!
    @IBOutlet weak var optionButton8: UIButton!
    
    
    @IBOutlet private var fruitButtons: [UIButton]!
    
    var score = 0
    var fruitness = Fruitness()
    
    
    override func viewDidLoad() {
        super.viewDidLoad()
        
        updateUI()
        
    }
    @IBAction func replayGame(_ sender: UIButton) {
        fruitness.restartGame() //Calling restart
        updateUI()
        
        
    }
    @IBAction func touchButton(_ sender: UIButton)  {
        
        let userAnswer = sender.currentTitle!
        
        //The userGotItRight is = to the checkAnswer function which goes through the fruitOptions array to make sure the answer is corrct. T/F
        let userGotItRight = checkAnswer(userAnswer: userAnswer)
        
        if userGotItRight {
            //Depending if the user got the answer correct the button turns green/red
            sender.backgroundColor = UIColor.green
        } else {
            sender.backgroundColor = UIColor.red
        }
        
        nextFruit() //Calling the next Fruit untill all the fruit items have been displayed.
        
        //This timer is responsible for the UIColors green, red and clear. Without this timer the color drags onto the next fruit.
        Timer.scheduledTimer(timeInterval: 0.2, target: self, selector: #selector(updateUI), userInfo:nil, repeats: false)
        
    }
    
    //    This check answer method needs an input to work. The input is the answer the user-choose (String).
    func checkAnswer(userAnswer: String) -> Bool {
        
        //        Checks if the user got the answer correct. T/F
        if userAnswer == fruitness.fruitOptions[fruitness.fruitNumber].fruit {
            fruitness.score += 1 //We increase the value of score when we get the answer right.
            //   fruitness.finalScorez = fruitness.score
            
            return true
        } else {
            return false
            
        }
    }
    //Checks to make sure the eveytime it hits 0 it will shuffle.
    func nextFruit() {
        if fruitness.fruitNumber == 0 {
            fruitness.fruitOptions.shuffle()
            
        }
        // print(fruitness.fruitOptions[fruitness.fruitNumber]) //Only gets printed in the consol
        
        if fruitness.fruitNumber + 1 < fruitness.fruitOptions.count {
            fruitness.fruitNumber += 1
        } else {
            self.performSegue(withIdentifier: "goToResultsVC", sender: self) //To call Segue
        }
    }
    
    //Connecting and controlling oF the Segue and from GameView COntroller -> Results view controller.
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if segue.identifier == "goToResultsVC" {
            let destinationVC = segue.destination as! ResultsViewController
            destinationVC.finalScore = scoreLabel.text //Printing the final score at the end.
        }
     
    }
    
    @objc func updateUI() {
        
        //Controlls the background. Clearing ability between T/F answers.
        optionButton0.backgroundColor = UIColor.clear
        optionButton1.backgroundColor = UIColor.clear
        optionButton2.backgroundColor = UIColor.clear
        optionButton3.backgroundColor = UIColor.clear
        optionButton4.backgroundColor = UIColor.clear
        optionButton5.backgroundColor = UIColor.clear
        optionButton6.backgroundColor = UIColor.clear
        optionButton7.backgroundColor = UIColor.clear
        optionButton8.backgroundColor = UIColor.clear
        
        //The fruit name available that the user needs to match.
        fruitLabel.text = fruitness.getFruitText()
        
        //Displaying the progress of the user till they reach the end.
        progressBar.progress = fruitness.getProgress()
        
        //Displaying the score at all times
        scoreLabel.text = "SCORE: \(fruitness.score)"
        
    }
    
    
}

你的代码有很多问题。

首先,prepare(for:sender:) 方法在触发 segue 的源视图控制器上调用,而不是在目标视图控制器上调用。

其次,您的 ResultsViewController 有一个 viewWillAppear(_:) 方法嵌套在其 prepare(for:sender:) 方法中。不要那样做。 viewWillAppear(_:) 方法必须是视图控制器的 top-level 方法,否则不会被调用。

另外,viewWillAppear(_:) 方法应该调用 super.viewWillAppear(animated).

您的 ResultsViewController 的 viewWillAppear 方法应如下所示:

func viewWillAppear(_ animated: Bool) {
    super.viewWillAppear(animated)
    finalScoreLabel.text = finalScore
}

GameViewController 中的 prepare(for:sender:) 方法应在 ResultsViewController 中设置 finalScore,以便在调用其 viewWillAppear 时,finalScore有一个值。

编辑:

(看起来你的最后一部分是正确的。你的 GameViewController 的 prepare(for:sender) 确实设置了 finalScore。但是请注意,你正在使用 scoreLabel 来保存你的 finalScoreValue。你不应该在视图对象中保存状态。你应该在 GameViewController 中有一个 var 来保存你的分数。你可以让 GameViewController 设置你的 score var,并有一个didSet() score var 上的方法,将更新的分数值安装到 scoreLabel 中。)

override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
    if segue.identifier == "goToResultsVC" {
        let destinationVC = segue.destination as! ResultsViewController
        destinationVC.finalScore = scoreLabel.text //Printing the final score at the end.
    }
 
}

也许您想将重复的代码重构为这个代码:

let optionButtonArray = [optionButton0,optionButton1 ...]
optionButtonArray.forEach { [=10=].backgroundColor = UIColor.clear }