Coding while Loading
Coding while Loading

Reputation: 413

storing object in user defaults swift

I'm new to swift and trying to figure out the best way to store user defaults. Here are my 3 initial VC classes of my app where i pass data from the on boarding view, to the start your plan view, to the user info (profile view) - which is where i need to store defaults for users. My issue is - the only user default that is storing is "name" and "monthly" pay seems to work as well. But the "daily budget default" and "daily savings default" (which are doubles) don't seem to store and appear on the 3rd screen, (users profile). I am not getting the correct reference.

1st snippet of code is from the on boarding view controller where i collect their info - to keep things short I'm only showing the calculateData IBAction. As of now - this is where i am trying to grab their user defaults.

2nd VC of info is the view directly after on boarding, where the user can review their info - once they press start from this VC- i create an new user object (should i just create an array of new User objects and store it under NSUserDefaults here?)

3rd VC - this is the actual user profile, where i need all of the user defaults to show. I am going to set this as the initial view controller & set up in app delegate, to load this page first if a user has previously done the on boarding screen.

Please and thank you for any help!

 import UIKit

 class ViewController: UIViewController, UITextFieldDelegate{

   @IBAction func calculateDataButtonPressed(_ sender: UIButton) {

    customerName = nameTextField.text!


    if let payTotal = Double(monthlyAmountTextField.text!){
        monthlyEarning = payTotal
    }

    if let savingsNumber = Double(desiredSavingsTextField.text!){
        desiredSavingsAmount = savingsNumber

    }

    else {
        displayLabel.text = "Enter input as so: 1299.39"

    }


    budgetForEachDay = ((monthlyEarning - desiredSavingsAmount) / 4.0) / 7.0
    savingsForEachDay = (desiredSavingsAmount / 4.0) / 7.0


    UserDefaults.standard.set(nameTextField.text, forKey: "name")
    UserDefaults.standard.set(monthlyAmountTextField.text, forKey: "monthlyPay")
    UserDefaults.standard.set(savingsForEachDay, forKey: "dailySavingsDefault")
    UserDefaults.standard.set(budgetForEachDay, forKey: "dailyBudgetDefault")
    //THE 4 USER DEFAULTS I NEED TO SAVE 

Here is the NEXT CLASS THAT THE SEGUE LOADS Too- i create a new User object here - should i perhaps store User Defaults in a newUserObject array instead of how i am trying to go about it ?

import UIKit

class StartYourPlanViewController: UIViewController {

    var nameFieldPassedOver : String?
    var monthlyEarningPassedOver : Double?
    var desiredSavingsPassedOver : Double?
    var budgetToSpend : Double = 55.3
    var saveEachDay : Double = 55.5



    @IBOutlet weak var nameLabel: UILabel!
    @IBOutlet weak var monthtlyEarningLabel: UILabel!
    @IBOutlet weak var desiredSavingsLabel: UILabel!


    override func viewDidLoad() {
        super.viewDidLoad()

        nameLabel.text = nameFieldPassedOver

        monthtlyEarningLabel.text = "\(monthlyEarningPassedOver!)" 
        monthtlyEarningLabel.isHidden = true

        desiredSavingsLabel.text = "\(desiredSavingsPassedOver!)"
        desiredSavingsLabel.isHidden = true


    }


    func makeNewUserObject(){

        let newUser = UserInfo(name: nameFieldPassedOver!, iWantToSave : desiredSavingsPassedOver!, monthlyIncome: monthlyEarningPassedOver!, budgetEachDay : budgetToSpend, youSaveEachDay : saveEachDay)


        newUser.printUserBio()

    }


    @IBAction func startPlanButtonPressed(_ sender: UIButton) {


        makeNewUserObject()



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

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


       if segue.identifier == "GoToYourUserInfoView"{

           let userInfoVC = segue.destination as! UserInfoViewController


            userInfoVC.userNamePassedOver = nameFieldPassedOver
            userInfoVC.userDailyBudgetPassedOver = budgetToSpend
            userInfoVC.userMonthlyEarningsPassedOver = monthlyEarningPassedOver
            userInfoVC.userDesiredSavingsPassedOver = desiredSavingsPassedOver
            userInfoVC.userDailySavingsPassedOver = saveEachDay

        }

    }


}

AND here will end up being my main and initial VC- where i display the users information for them. I need to Set the default values of user defaults so that they appear on this page everytime an existing user opens the app

class UserInfoViewController : ViewController {

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

    let monthlyPay = "monthlyPay"
    let name = "name"
    let dailySavingsDefault = "dailySavingsDefault"
    let dailyBudgetDefault = "dailyBudgetDefault"


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


    override func viewDidLoad() {
        super.viewDidLoad()



        if let name = UserDefaults.standard.value(forKeyPath: name) as? String{
            userNameLabel.text = name
        }

        if let monthlyPay = UserDefaults.standard.value(forKeyPath: monthlyPay) as? String{

            userMonthlyEarningsPassedOver = Double(monthlyPay)

        }

      if let dailySavingsDefault = UserDefaults.standard.value(forKeyPath: dailySavingsDefault) as? String{



            dailySavingsNumberLabel.text = dailySavingsDefault



        }

       if let dailyBudgetDefault = UserDefaults.standard.value(forKeyPath: dailyBudgetDefault) as? String {

            dailySpendingLimitLabel.text = dailyBudgetDefault


        }


    }

Upvotes: 0

Views: 4885

Answers (3)

oskarko
oskarko

Reputation: 4178

If you want to store structs on UserDefaults:

// Save the selected timeZone on UserDefaults
    if let encodedCity = try? JSONEncoder().encode(cityAndTimeZone) {
       UserDefaults.standard.set(encodedCity, forKey: "cityAndTimeZone")
    }


// To restore struct from UserDefaults
if let decodedData = UserDefaults.standard.object(forKey: "cityAndTimeZone") as? Data {
        if let cityAndTimeZone = try? JSONDecoder().decode(CityAndTimeZone.self, from: decodedData) {
            timezoneLabel.text = cityAndTimeZone.city
        }
    }

Upvotes: 0

Chetan Rajauria
Chetan Rajauria

Reputation: 209

Initially, You have to archive the objects into NSData then we can save it to the UserDefault and retrieve it from UserDefault when needed.

Example is shown below:-

1) Save object to UserDefault

let groups = [Group(id: 1, name: "group1", shortname: "g1"), Group(id: 2, name: "group2", shortname: "g2")]

var userDefaults = UserDefaults.standard
let encodedData: Data = NSKeyedArchiver.archivedData(withRootObject: groups)
userDefaults.set(encodedData, forKey: "groups")
userDefaults.synchronize()

2) Retrieve Object from UserDefault

let decoded  = userDefaults.object(forKey: "groups") as! Data
let decodedGroups = NSKeyedUnarchiver.unarchiveObject(with: decoded) as! [Group]

Upvotes: 5

dahiya_boy
dahiya_boy

Reputation: 9503

When you set the data is userdefault after it you have to synchronise your userdefault so that userdefault saves the pending data. Make sure you won't have any typo mistake with userdefault identifier.

Upvotes: -1

Related Questions