sUnit1
sUnit1

Reputation: 57

Global variable doesn't increase? - also want to save global variable even after app closes

I'm now trying to learn about global variables that can be used across many different parts of an app.

I'm trying to create a global variable "Quarters" that can be used in any part of my app and that will save whatever the current value is even after the app is closed/quit.

My code below is not increasing my "quarters" variable. It just stays at 0. There are no errors either. I can get it to work if I have the variable inside the struct ContentView, but not if I try to make it a global variable.

import SwiftUI

struct MyVariables {
    var quarters:Int = 0
}

struct ContentView: View {
    //@State private var quarters = 0 - if I point to the variable this way, it works
    var body: some View {
        VStack {
        Text("\(MyVariables.quarters)").bold()
        Button(action: {
            MyVariables.quarters += 1
        }) {
            Image("QuarterMachine")
        }
    }
}
}

I believe the below two codes can be used to save the variable, but I'm not certain since I can't figure out the above part first.

import Foundation

protocol Storage {

    var quarters: Int { get }
    
    func save(quarters: Int)
}

And also

import Foundation

class LocalStorage: Storage {
    private let quartersKey = "quarters"
    
    func reset() {
        save(quarters: 0)
    }

    var quarters: Int {
        UserDefaults().integer(forKey: quartersKey)
    }

    func save(quarters: Int) {
        UserDefaults().set(quarters, forKey: quartersKey)
    }
}

Upvotes: 1

Views: 141

Answers (1)

Roland Lariotte
Roland Lariotte

Reputation: 3488

To save a value across all SwiftUI views and save it the same way UserDefaults would do, you can use @AppStorage. Just use the same key, "quarters" in this example, in the other views to retrieve the saved value.

As for answering your concern on how to update your value elsewhere that on the button tap, you can use a view model to handle all your logic and use @AppStorage out of your view.

struct ContentView: View {

  @StateObject var viewModel = GameViewModel()

  var body: some View {
    VStack {
      Text("\(viewModel.quarters)")
        .bold()

      Button(action: { viewModel.quarters += 1 }) {
        Image("QuarterMachine")
      }
    }
  }
}

This is the view model to handle your logic.

final class GameViewModel: ObservableObject {

  @AppStorage("quarters")
  var quarters: Int = .zero

  // You can use this method in your code to increase
  // your quarters value when your game is finished.
  func finishGame() {
    quarters += 1
  }
}

Upvotes: 1

Related Questions