I am working on a tip tracker app that lets the user input as many tip values that they want, while showing them their input and also calculating a total and average. I am trying to use UserDefaults to save two doubles (totalValueOfAllTips, numberOfTipsTracked) and one string (sampleLog.text)
I want it to show the same data in `sampleLog`, `totalLabel`, and `avgLabel` every time the user re-opens the app.
Here is my TipTrackerViewController class, along with protocols that calculate the total, number of tips, and average value:
import UIKit
protocol TipTrackerProtocol {
var totalValueOfAllTips: Double { get }
var numberOfTipsTracked: Int { get }
}
extension TipTrackerProtocol {
var averageTip: Double {
return round((totalValueOfAllTips / Double(numberOfTipsTracked)) * 100) / 100
}
}
class TipTrackerViewController: UIViewController, TipTrackerProtocol {
var numberOfTipsTracked = 0 // store as user default
var valDollar = 0
var valCent = 0
var totalValueOfAllTips = 0.0 // store as user default
@IBOutlet weak var dollarLabel: UILabel!
@IBOutlet weak var centLabel: UILabel!
@IBOutlet weak var sampleLog: UITextView! // store all values in sampleLog as user defaults
@IBOutlet weak var totalLabel: UILabel!
@IBOutlet weak var avgLabel: UILabel!
@IBOutlet weak var dollarsStepper: UIStepper!
@IBOutlet weak var centsStepper: UIStepper!
// Dollar Stepper
@IBAction func stepper(_ sender: UIStepper) {
dollarLabel.text = "$\(Int(sender.value))"
valDollar = Int(sender.value)
}
// Cent Stepper
@IBAction func stepperCent(_ sender: UIStepper) {
centLabel.text = ".\(Int(sender.value))"
if sender.value == 0 {
centLabel.text = ".00"
}
valCent = Int(Double(sender.value))
}
@IBAction func addTipButton(_ sender: UIButton) {
let numberFormatter = NumberFormatter()
numberFormatter.minimumFractionDigits = 2
numberFormatter.maximumFractionDigits = 2
numberFormatter.minimumIntegerDigits = 1 /
let tipDollarCent = (dollarLabel.text ?? "$0") + (centLabel.text ?? ".00")
let tipValue = getTipValue()
totalValueOfAllTips += tipValue
numberOfTipsTracked += 1
sampleLog.text! += "\(tipDollarCent)\n"
let totalLabelStringValue = numberFormatter.string(from: totalValueOfAllTips as NSNumber)
let averageLabelStringValue = numberFormatter.string(from: averageTip as NSNumber)
totalLabel.text! = "$" + totalLabelStringValue!
avgLabel.text! = "$" + averageLabelStringValue!
dollarLabel.text = "$0"
centLabel.text = ".00"
valDollar = 0
valCent = 0
dollarsStepper.value = 0
centsStepper.value = 0
}
override func viewDidLoad() {
super.viewDidLoad()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
/
@IBAction func backButtonPressed(_ sender: Any) {
navigationController?.popViewController(animated: true)
}
private func getTipValue() -> Double {
let valueOfCents = Double(valCent) / 100
return Double(valDollar) + valueOfCents
}
}I tried the following implementation inside of my viewDidLoad function, at least for the total tip value:
UserDefaults.standard.set(totalValueOfAllTips, forKey: _totalValueOfAllTips) // write to user defaults
UserDefaults.standard.double(forKey: _totalValueOfAllTips) // read from user default when view loadsBased on my research and the errors Xcode gives me, I am not putting the UserDefault commands within the proper scope, because I'm sure my syntax is correct.