Swift passing calculated data back to previous view controller

Coding while Loading picture Coding while Loading · Mar 10, 2018 · Viewed 13.2k times · Source

I am creating my first simple budgeting app. Basically, I take a few user inputs like monthly income & savings goal. Then they click "start", & the app calculates stuff such as, their daily budget etc.

Here I'm running into trouble. After all the calculations, I display "how much you can spend each day" (e.g. $20 a day), which I pass forward through segues from their original inputs on the original screen.

Now, in this VC (UserInfoVC) I created a button which lets them add how much money they spent today. So when they click this "add money spent" button, I open a new VC (AddSubtractMoney) where I present a calculator where they can enter how much they spent today (i.e. $12) and click submit.

I run their input compared to their daily budget to get a New daily budget.

Now, I'm having trouble passing this updated number backwards, to display it on the previous VC on the label "dailySpendingLimitLabel". I know segues are not the best way to go about passing data backwards.

I've tried closures, but I end up getting lost in the syntax, and protocols and delegates (it's my 2nd month coding).

Is there a simple way to achieve passing this data back to the previous VC and populating the data in that previous display label?

Below is the code.

The First snippet is from the UserInfoVC where I display their originally entered data that I segued through. The Second snippet is from the AddSubtractMoney class where I placed the calculator and created an object "newestUpdate" inside a function that allows me to calculate the number they entered on the calculator minus their old daily budget. To arrive at a new budget which I want to present backwards to the UserInfoVC.

class UserInfoViewController : ViewController {

var userNamePassedOver : String?
var userDailyBudgetPassedOver : Double = 99.0
var userDailySavingsPassedOver : Double = 778.00
var userMonthlyEarningsPassedOver : Double?
var userDesiredSavingsPassedOver : Double?
var newAmountPassedBack : Double = 0.0


@IBOutlet weak var dailySavingsNumberLabel: UILabel!
@IBOutlet weak var userNameLabel: UILabel!
@IBOutlet weak var dailySpendingLimitLabel: UILabel!



override func viewDidLoad() {
    super.viewDidLoad()

    userNameLabel.text = userNamePassedOver
    dailySpendingLimitLabel.text = String(format: "%.2f", userDailyBudgetPassedOver)
    dailySavingsNumberLabel.text = String(format: "%.2f", userDailySavingsPassedOver)

}


@IBAction func addSubtractMoneyPressed(_ sender: UIButton) {

    performSegue(withIdentifier: "addOrSubtractMoney", sender: self)


}

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

    if segue.identifier == "addOrSubtractMoney"{

        let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney

            addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
        }
    }

}

extension UserInfoViewController: AddSubtractMoneyDelegate {

func calculatedValue(value: Double) {

    dailySpendingLimitLabel.text = String(userDailyBudgetPassedOver - value)

}

}

import UIKit

protocol AddSubtractMoneyDelegate {
  func calculatedValue(value: Double)
}

class AddSubtractMoney: UIViewController {

@IBOutlet weak var outputLabel: UILabel!

var runningNumber = ""
var finalNumberPassedOver : Double?
var amountPassedBackToUserInfo : Double = 0.0
var dailyBudgetPassedThrough : Double = 0.0

var delegate: AddSubtractMoneyDelegate?

override func viewDidLoad() {
    super.viewDidLoad()

    outputLabel.text = "0"


    // Do any additional setup after loading the view.
}


@IBAction func buttonPressed(_ sender: UIButton) {
    runningNumber += "\(sender.tag)"
    outputLabel.text = runningNumber


}

@IBAction func submitNewInfo(_ sender: UIButton) {

    // FIX FIX

    AddSubtractMoneyController.addToMoneySpentArray(amountISpent: outputLabel.text!)

    sendBackUpdatedNumber()

    dismiss(animated: true, completion: nil)

}


@IBAction func allClearedPressed(_ sender: UIButton) {
    runningNumber = ""
    outputLabel.text = "0"
}

// THIS LINE PRODUCES THE CORRECT INPUT IN OUTPUT CONSOLE WHEN I PRINT- BUT I CANT FIGURE HOW TO TRANSFER IT BACK TO PREVIOUS VC

func sendBackUpdatedNumber(){

    let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)

   amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
   newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo

    print(amountPassedBackToUserInfo)

    self.delegate?.calculatedValue(value: amountPassedBackToUserInfo)


}


}

Answer

vadian picture vadian · Mar 10, 2018

My suggestion is to use a callback closure. It's less code and easier to handle than protocol / delegate.

In AddSubtractMoney declare a callback variable and call it in sendBackUpdatedNumber passing the Double value

class AddSubtractMoney: UIViewController {

   // ...

    var callback : ((Double)->())?

  // ...

    func sendBackUpdatedNumber(){

        let newestUpdate = UserInfo(whatYouSpentToday: runningNumber, oldDailyBudgetPassed: dailyBudgetPassedThrough)
        amountPassedBackToUserInfo = dailyBudgetPassedThrough - Double(runningNumber)!
        newestUpdate.goalToSaveDaily = amountPassedBackToUserInfo
        print(amountPassedBackToUserInfo)
        callback?(amountPassedBackToUserInfo)
    }
}

In prepare(for segue assign the closure to the callback variable and add the code to be executed on return

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

    if segue.identifier == "addOrSubtractMoney"{
        let addOrSubtractMoneyVC = segue.destination as! AddSubtractMoney
        addOrSubtractMoneyVC.callback = { result in
             print(result)
            // do something with the result
        }
        addOrSubtractMoneyVC.dailyBudgetPassedThrough = userDailyBudgetPassedOver
    }
}