Home > Blockchain >  How can I reset @AppStorage data when an App Storage variable is 0?
How can I reset @AppStorage data when an App Storage variable is 0?

Time:08-03

import SwiftUI

struct characterDetail: View {
    
    @AppStorage("USER_HEALTH") var userHealth = 100
    @AppStorage("GOLD") var gold = 100
    @AppStorage("USER_PRESTIGE") var userPrestige = 0
    @AppStorage("USER_GLORY") var userGlory = 0
    @AppStorage("USER_ARMOR") var userArmor = 0
    @AppStorage("USER_SPEED") var userSpeed = 0
    @AppStorage("USER_DAMAGE") var userDamage = 0
    

    
    var body: some View {
        VStack{
            ZStack{
                Rectangle()
                    .fill(.gray.opacity(0.1))
                    .cornerRadius(20)
                HStack{
                    Image("character")
                        .resizable()
                        .frame(width: 100, height: 100)

                    VStack(alignment: .leading) {
                        Text("Character Stats")
                            .bold()
                        Text("Health: \(userHealth)")
                            
                        Text("Gold: \(gold)")
                           
                        Text("Prestige: \(userPrestige)")
                        
                        Text("Glory: \(userGlory)")
                            
                    }
                    .offset(x:0, y:-10)
                }
            
            }
        }
        .frame(width: 350, height: 200)
    }
}

Every time I finish the missions user health goes down. When its come to 0 I wanna reset those all variables. Or the app get back to first shape like first time you build.

A restart function for game I tried to do someone but I couldn't. I hope I will find what I am looking for. Thank you for your help.

import SwiftUI

struct firstMissionButton: View {
    @AppStorage("USER_HEALTH") var userHealth = 100
    @State private var countDownTimer = 5
    @State private var timerRuning = false
    private let timer = Timer.publish(every: 1, on: .main, in: .common).autoconnect()
    var body: some View {
        VStack{
            
            Button(action:{
                timerRuning = true
                userHealth -= 20
            } ){
                Text("GO! Mission Time: \(countDownTimer) sec.")
            }.onReceive(timer){_ in
                if countDownTimer > 0 && timerRuning {
                    countDownTimer -= 1
                }
                else {
                    timerRuning = false
                    countDownTimer = 5
            }
            }.disabled(timerRuning)
        }
    }
}

struct firstMissionButton_Previews: PreviewProvider {
    static var previews: some View {
        firstMissionButton()
    }
}

this is the place I change the userHealth.

CodePudding user response:

I would recommend using an enum for the keys of your @AppStorage. This would also provide some sort of safety regarding typos in the String declaration in @Appstorage.

enum UserKeys: String, CaseIterable{
    case health = "USER_HEALTH"
    case gold = "GOLD"
    case prestige = "USER_PRESTIGE"
    case glory = "USER_GLORY"
    case armor = "USER_ARMOR"
    case speed = "USER_SPEED"
    case damage = "USER_DAMAGE"
}

Then create an extension for UserDefaults that removes exactly these keys:

extension UserDefaults {
    func resetUser(){
        UserKeys.allCases.forEach{
            removeObject(forKey: $0.rawValue)
        }
    }
}

Usage:

@AppStorage(UserKeys.health.rawValue) var userHealth = 100
@AppStorage(UserKeys.gold.rawValue) var gold = 100
@AppStorage(UserKeys.prestige.rawValue) var userPrestige = 0
@AppStorage(UserKeys.glory.rawValue) var userGlory = 0
@AppStorage(UserKeys.armor.rawValue) var userArmor = 0
@AppStorage(UserKeys.speed.rawValue) var userSpeed = 0
@AppStorage(UserKeys.damage.rawValue) var userDamage = 0

and the function to remove would be:

UserDefaults.standard.resetUser()

It would be best to check for userHealth == 0 and call the removeUser function at the place where you decrement it. But that is not shown in your code example.

Edit:

It should be something like this but without knowing the rest of your logic it is hard to say if the timer should execute after userHealth is below or at zero:

Button(action:{
    
    userHealth -= 20
    if userHealth <= 0{
        UserDefaults.standard.resetUser()
        return
    }

    timerRuning = true
}

Remarks:

This is just a hunch and not related to the question, but I think it would be best to move the code for manipulating an checking the health property to the else clause of the timer fired function.

CodePudding user response:

I think it’s already posted here, but try the following function:

extension UserDefaults {
    func resetDefaults() {
        let dictionary = self.dictionaryRepresentation()
        dictionary.keys.forEach({self.removeObject(forKey: $0})
    }
}
  • Related