TheBrewery
TheBrewery

Reputation: 25

Refresh parent UIViewController after presented UIViewController dismisses

I have a MainVC that is used to select which element to edit, it consists of four buttons and four labels. When you select a button it passes and ID for the button (via prepare) and executes the segue (Present Modally). After the user enters data the press a "save" button it applies the data to a global var and calls self.dismiss.

The issue comes when we go back to the MainVC it does not update the Labels.

I have a function that creates the string and applies it to the UILabel.text and have tried adding it to viewDidLoad and viewWillAppear with no success so I have added a "refresh" button that calls the function and that works but I would prefer it if the dang thing would update automatically.

MainVC code:

//
//  ViewController.swift
//  IBS Club Match Scoring
//
//  Created by Michael Brewer on 2/11/21.
//

import UIKit

var mainVC = ViewController()

class ViewController: UIViewController {
    
    struct GlobalVars {
        static var scoreTarget1 = 0
        static var scoreTarget2 = 0
        static var scoreTarget3 = 0
        static var scoreTarget4 = 0
        static var xCountTarget1 = 0
        static var xCountTarget2 = 0
        static var xCountTarget3 = 0
        static var xCountTarget4 = 0
//        static var matchTotal = "0 - 0X"
//        static var overallScore = 0
//        static var overallXCount = 0
        
//        func updateScores() {
//            var target1ScoreText = "\(ViewController.GlobalVars.scoreTarget1) - \(ViewController.GlobalVars.xCountTarget1)X"
//            var target2ScoreText = "\(ViewController.GlobalVars.scoreTarget2) - \(ViewController.GlobalVars.xCountTarget2)X"
//            var target3ScoreText = "\(ViewController.GlobalVars.scoreTarget3) - \(ViewController.GlobalVars.xCountTarget3)X"
//            var target4ScoreText = "\(ViewController.GlobalVars.scoreTarget4) - \(ViewController.GlobalVars.xCountTarget4)X"
//            ViewController.GlobalVars.overallScore = ViewController.GlobalVars.scoreTarget1 + ViewController.GlobalVars.scoreTarget2 + ViewController.GlobalVars.scoreTarget3 + ViewController.GlobalVars.scoreTarget4
//            ViewController.GlobalVars.overallXCount = ViewController.GlobalVars.xCountTarget1 + ViewController.GlobalVars.xCountTarget2 + ViewController.GlobalVars.xCountTarget3 + ViewController.GlobalVars.xCountTarget4
//            ViewController.GlobalVars.matchTotal = "\(ViewController.GlobalVars.overallScore) - \(ViewController.GlobalVars.overallXCount)X"
//        }
    }
    //Variables
    var whatTargetIsThis = 0
//    var whatTargetWasThis = 0
    var matchTotal = "0 - 0X"
    var overallScore = 0
    var overallXCount = 0
//    var btnID = ""
    
    
    //Upper Display
    @IBOutlet weak var matchTotalLabel: UILabel!
    @IBOutlet weak var matchTotalScore: UILabel!
    
    //Target Scores
    @IBOutlet weak var target1Score: UILabel!
    @IBOutlet weak var target2Score: UILabel!
    @IBOutlet weak var target3Score: UILabel!
    @IBOutlet weak var target4Score: UILabel!
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if(segue.identifier == "enterScoresSeg"){
                let entryVC = segue.destination as! ScoringUI
            entryVC.targetNumber = whatTargetIsThis
        }
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
//        print("this was target number \(whatTargetWasThis)")
       // print(ViewController.GlobalVars.scoreTarget1)
//        updateScores()
    }
    
//    override func viewWillAppear(_ animated: Bool) {
//       // updateScores()
//    }
    
//    override func setNeedsFocusUpdate() {
//        updateScores()
//    }
    
    func updateScores() {
        target1Score.text  = "\(ViewController.GlobalVars.scoreTarget1) - \(ViewController.GlobalVars.xCountTarget1)X"
        target2Score.text = "\(ViewController.GlobalVars.scoreTarget2) - \(ViewController.GlobalVars.xCountTarget2)X"
        target3Score.text = "\(ViewController.GlobalVars.scoreTarget3) - \(ViewController.GlobalVars.xCountTarget3)X"
        target4Score.text = "\(ViewController.GlobalVars.scoreTarget4) - \(ViewController.GlobalVars.xCountTarget4)X"
        overallScore = ViewController.GlobalVars.scoreTarget1 + ViewController.GlobalVars.scoreTarget2 + ViewController.GlobalVars.scoreTarget3 + ViewController.GlobalVars.scoreTarget4
        overallXCount = ViewController.GlobalVars.xCountTarget1 + ViewController.GlobalVars.xCountTarget2 + ViewController.GlobalVars.xCountTarget3 + ViewController.GlobalVars.xCountTarget4
        matchTotalScore.text = "\(overallScore) - \(overallXCount)X"
    }
    
   
    @IBAction func refreshDisplay(_ sender: UIButton) {
        updateScores()
    }
    
    
    // Go-To Target Buttons
    
    @IBAction func targetBtn(_ sender: UIButton) {
        switch sender.titleLabel?.text {
        case "Target 1":
            whatTargetIsThis = 1
        case "Target 2":
            whatTargetIsThis = 2
        case "Target 3":
            whatTargetIsThis = 3
        case "Target 4":
            whatTargetIsThis = 4
        default:
            break
        }
        self.performSegue(withIdentifier: "enterScoresSeg", sender:self)
    }

}

Second VC code:

//
//  ScoringUI.swift
//  IBS Club Match Scoring
//
//  Created by Michael Brewer on 2/11/21.
//

import UIKit

class ScoringUI: UIViewController {

    //Variables
    var targetNumber = 0
    var runningScore = 0
    var runningX = 0
    var runningTotal = " "
    var keyPressed = 0
    var addAnX = 0
    var shots = ["-","-","-","-","-"]
    var i = 0
    var shot = ""
    var shotsListed = ""
    //Display boxes for each shot
    @IBOutlet weak var eachShot: UILabel!

    //Display target score
    @IBOutlet weak var targetScore: UILabel!
    @IBOutlet weak var mosesFU: UIImageView!
    
    func sendScoresToMain() {
        
        switch targetNumber {
        case 1:
            ViewController.GlobalVars.scoreTarget1 = runningScore
            ViewController.GlobalVars.xCountTarget1 = runningX
            print("running case 1")
        case 2:
            ViewController.GlobalVars.scoreTarget2 = runningScore
            ViewController.GlobalVars.xCountTarget2 = runningX
        case 3:
            ViewController.GlobalVars.scoreTarget3 = runningScore
            ViewController.GlobalVars.xCountTarget3 = runningX
        case 4:
            ViewController.GlobalVars.scoreTarget4 = runningScore
            ViewController.GlobalVars.xCountTarget4 = runningX
        default:
            break
        }
        
    }
    
    override func viewDidLoad() {
        super.viewDidLoad()
        print(targetNumber)
    }
    
    
    func updateView() {
        if i < 5 {
            runningScore += keyPressed
            runningX += addAnX
            shots[i] = shot
            //Update total score
            if runningScore > 0 && runningX >= 0 {
                runningTotal = "\(runningScore) - \(runningX) X"
            } else {
                runningTotal = "0 - 0X"
            }
            targetScore.text = runningTotal
            shotsListed = "\(shots[0]), \(shots[1]), \(shots[2]), \(shots[3]), \(shots[4])"
            eachShot.text = shotsListed
            if runningScore == 50 {
                mosesFU.alpha = 1
                targetScore.textColor = UIColor.white
            }
            i += 1
        }
    }

    //Keypad to enter scores
    
    @IBAction func buttonX(_ sender: UIButton) {
        keyPressed = 10
        addAnX = 1
        shot = "X"
        updateView()
    }
    @IBAction func button10(_ sender: UIButton) {
        keyPressed = 10
        addAnX = 0
        shot = "10"
        updateView()
    }
    @IBAction func button9(_ sender: UIButton) {
        keyPressed = 9
        addAnX = 0
        shot = "9"
        updateView()
    }
    @IBAction func button8(_ sender: UIButton) {
        keyPressed = 8
        addAnX = 0
        shot = "8"
        updateView()
    }
    @IBAction func button7(_ sender: UIButton) {
        keyPressed = 7
        addAnX = 0
        shot = "7"
        updateView()
    }
    @IBAction func button6(_ sender: UIButton) {
        keyPressed = 6
        addAnX = 0
        shot = "6"
        updateView()
    }
    @IBAction func button5(_ sender: UIButton) {
        keyPressed = 5
        addAnX = 0
        shot = "5"
        updateView()
    }
    @IBAction func button0(_ sender: UIButton) {
        keyPressed = 0
        addAnX = 0
        shot = "0"
        updateView()
    }
    @IBAction func buttonM(_ sender: UIButton) {
        keyPressed = -51
        addAnX = -6
        shot = "M"
        updateView()
    }
    
    @IBAction func resetDisplay(_ sender: UIButton) {
        runningScore = 0
        runningX = 0
        runningTotal = " "
        keyPressed = 0
        addAnX = 0
        shots = ["-","-","-","-","-"]
        i = 0
        shot = ""
        shotsListed = ""
        if runningScore > 0 && runningX >= 0 {
            runningTotal = "\(runningScore) - \(runningX) X"
        } else {
            runningTotal = "0 - 0X"
        }
        targetScore.text = runningTotal
        eachShot.text = shotsListed
        mosesFU.alpha = 0
        targetScore.textColor = UIColor.black
        
    }
    @IBAction func back(_ sender: Any) {
        sendScoresToMain()
        self.dismiss(animated: true, completion: nil)
    }
    @IBAction func removeLastShot(_ sender: UIButton) {
        if i >= 1 {
            i -= 1
            switch shots[i] {
            case "X":
                runningScore -= 10
                runningX -= 1
            case "10":
                runningScore -= 10
            case "9":
                runningScore -= 9
            case "8":
                runningScore -= 8
            case "7":
                runningScore -= 7
            case "6":
                runningScore -= 6
            case "5":
                runningScore -= 5
            case "0":
                runningScore -= 0
            case "M":
                runningScore += 51
                runningX += 6
            default:
                return
            }
            
            shots[i] = "-"
            if runningScore > 0 && runningX >= 0 {
                runningTotal = "\(runningScore) - \(runningX) X"
            } else {
                runningTotal = "0 - 0X"
            }
            targetScore.text = runningTotal
            shotsListed = "\(shots[0]), \(shots[1]), \(shots[2]), \(shots[3]), \(shots[4]), "
            eachShot.text = shotsListed
        }
    }


}

Upvotes: 1

Views: 47

Answers (1)

Tomas Jablonskis
Tomas Jablonskis

Reputation: 4376

Pass a closure to your second view controller and call it when dismissal of the second controller completes or even before that if you want:

class ScoringUI: UIViewController {

    var onDismissed: (() -> Void)? = nil       

    // ...

    @IBAction func back(_ sender: Any) {
        sendScoresToMain()
        self.dismiss(animated: true) { [weak self] in
             guard let self = self else { return }
             self.onDismissed?()
        }
    }

    // ...
}

class ViewController: UIViewController {
    // ...
    
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        if(segue.identifier == "enterScoresSeg") {
            guard let entryVC = segue.destination as? ScoringUI else { return }
            entryVC.targetNumber = whatTargetIsThis
            entryVC.onDismissed = {
                // UPDATE UI HERE
            }
        }
    }

    // ...
}

By the way, I would discourage you from using globals, better make a data model that you can pass around between view controllers. By doing that you could change above code to pass that data model into var onDismissed: ((_ newData: MyDataModel) -> Void)? = nil and receive it at the other end and update your UI accordingly.

Upvotes: 1

Related Questions