skip to Main Content
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.

2

Answers


  1. 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})
        }
    }
    
    Login or Signup to reply.
  2. 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.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search