SwiftUI开发游戏如何实现最高分退出APP后仍可持久化保存?
解决方案
你可以用SwiftUI内置的@AppStorage属性包装器实现最高分的持久化,它会自动将数值存储到系统UserDefaults中,应用重启后自动读取已保存的数值,无需手动编写读写逻辑,适配iOS 14及以上版本。
修改步骤
- 替换
highScore的属性声明
将原来的:
@State private var highScore = 0
修改为:
@AppStorage("highScore") private var highScore = 0
括号内的"highScore"是本地存储的唯一键名,保持固定即可。
- 原有更新最高分的逻辑无需额外调整,
@AppStorage会在你给highScore赋值时自动同步到本地存储,下次应用启动时会自动读取本地保存的值作为初始值。
适配iOS 13及以下版本的方案
如果需要兼容更低版本系统,可以手动操作UserDefaults实现读写:
- 初始化时读取本地存储的最高分:
@State private var highScore = UserDefaults.standard.integer(forKey: "highScore")
- 调整最高分更新逻辑,赋值后同步写入本地:
func highScoreSet() { if highScore < userScore { highScore = userScore UserDefaults.standard.set(highScore, forKey: "highScore") } }
注:你原有highScoreSet方法的入参number全程没有用到,属于冗余参数,可以直接删除,调用时也不需要传值。
优化后的完整代码
import SwiftUI struct Europe: View { @State private var countries = ["Albania", "etc."].shuffled() // 修正拼写错误,原corrrectAnswer改为correctAnswer @State private var correctAnswer = Int.random(in: 0...5) @State private var showingScore = false @State private var scoreTitle = "" @State private var userScore = 0 // 用@AppStorage实现持久化 @AppStorage("highScore") private var highScore = 0 var body: some View { ZStack{ LinearGradient(gradient: Gradient(colors: [.white,.blue]), startPoint: .top, endPoint: .bottom).edgesIgnoringSafeArea(.all) VStack(spacing:30){ VStack{ Text("Tap the flag of") .foregroundColor(.black) .fontWeight(.black) Text(countries[correctAnswer]) .foregroundColor(.black) .font(.largeTitle) .fontWeight(.black) } VStack(spacing:50){ HStack(spacing:40) { VStack(spacing:40) { ForEach(0..<3){ number in Button(action: { self.flagTapped(number) self.highScoreSet() }){ Image(self.countries[number]) .resizable() .frame(width: 130, height: 100) .clipShape(Capsule()) .overlay(Capsule().stroke(Color.black,lineWidth: 1)) .shadow(color: .black, radius: 2) } } } VStack(spacing:40) { ForEach(4..<7){ number in Button(action: { self.flagTapped(number) self.highScoreSet() }){ Image(self.countries[number]) .resizable() .frame(width: 130, height: 100) .clipShape(Capsule()) .overlay(Capsule().stroke(Color.black,lineWidth: 1)) .shadow(color: .black, radius: 2) } } } } VStack{ Text("Score: \(userScore)") .foregroundColor(.white) .fontWeight(.black) .font(.subheadline) Text("High Score: \(highScore)") .foregroundColor(.white) .fontWeight(.black) .font(.subheadline) } Spacer() } } } .alert(isPresented: $showingScore){ Alert(title: Text(scoreTitle), message: Text("Your score is \(userScore)"), dismissButton: .default(Text("Continue")){ self.askQuestion()}) } } // 移除冗余的number参数 func highScoreSet(){ if highScore < userScore { highScore = userScore } } func flagTapped(_ number: Int){ if number == correctAnswer{ scoreTitle = "Right" userScore += 1 } else { scoreTitle = "Wrong!\n Thats the flag of \(countries[correctAnswer])" userScore = 0 } showingScore = true } func askQuestion(){ countries.shuffle() correctAnswer = Int.random(in: 0...5) } } struct Europe_Previews: PreviewProvider { static var previews: some View { ContentView() } }
内容的提问来源于stack exchange,提问作者Adal Chang
相关产品推荐
相关产品推荐

