Reputation: 43
I am creating a simple counter application where the user can set a maximum number of patrons allowed in their place of business and when that number is reached they're given a notification that they're at maximum capacity. I'm using UserDefaults to store this data, however whenever I update the max number in the settings and return to the main view it's still using the previous max number. If I close the app and reopen it has the correct data. How do I make sure the data is being updated in the main view controller so it receives proper data?
ViewController.swift (main view controller)
import UIKit
import AVFoundation
class ViewController: UIViewController {
var counter = 0;
var max = UserDefaults.standard.integer(forKey: "max");
// Max patron alert function
func showAlert() {
let alertController = UIAlertController(title: "Limit Reached", message: "Your place of business has reached maximum capacity, please stop patrons from entering until capacity dissipates.", preferredStyle: .alert)
alertController.addAction(UIAlertAction(title: "Dismiss", style: .default))
self.present(alertController, animated: true, completion: nil)
AudioServicesPlaySystemSound(kSystemSoundID_Vibrate)
}
@IBOutlet weak var count: UILabel!
@IBAction func increment(_ sender: UIButton) {
if counter < max {
counter += 1;
count?.text = String(counter);
}
if counter == max {
showAlert();
}
}
@IBAction func decrement(_ sender: UIButton) {
if (counter == 0) {
counter += 0;
}
else {
counter -= 1;
}
count?.text = String(counter);
}
@IBAction func reset(_ sender: UIButton) {
counter = 0;
count?.text = String(counter);
}
override func viewDidLoad() {
super.viewDidLoad()
// UserDefaults.standard.synchronize()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
SettingsViewController.swift
import UIKit
class SettingsViewController: UIViewController {
var mainViewController:ViewController?;
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
@IBOutlet weak var maxOccupancy: UITextField!
@IBAction func save(_ sender: UIButton) {
let max = Int(maxOccupancy.text!);
UserDefaults.standard.set(max, forKey: "max")
UserDefaults.standard.synchronize()
print(UserDefaults.standard.integer(forKey: "max"))
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
// Get the new view controller using segue.destination.
// Pass the selected object to the new view controller.
}
*/
}
Upvotes: 0
Views: 1659
Reputation: 17844
This line:
var max = UserDefaults.standard.integer(forKey: "max")
is executed only once, when ViewController
is created. (BTW: no need for semicolons in Swift). Whatever happens to UserDefaults
afterwards won't be reflected in its value.
Replace the line with
var max: Int {
UserDefaults.standard.integer(forKey: "max")
}
so that every access to it actually goes out to fetch the value from UserDefaults
.
These constructs are called "Computed Properties", explained here.
Upvotes: 3
Reputation: 3143
This happens because you read the counter number only once when ViewController
is allocated. You might try to re-read it when ViewController
will appear on the screen:
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
max = UserDefaults.standard.integer(forKey: "max")
}
Also, no need to use ;
in every line's ending, Swift doesn't require it.
Upvotes: 1