实现核心数据的问题



我又带着另一个可能很愚蠢的问题回来了,哈哈。我正在扩展我在YouTube教程中找到的直升机游戏作为学习练习。我所坚持的部分是,我试图使用核心数据来允许用户在死亡时保存他们的分数,并在游戏主屏幕的单独视图中回忆这些保存的分数(我在主屏幕中使用ContentView,在实际游戏中使用单独的GameView)。在我的数据模型中,我定义了一个单独的实体"Scores"和一个单独的属性"name"。核心数据的使用在GameView文件返回没有错误,但当我试图在视图中获取数据,我想列出的分数,我得到错误:

类型'FetchedResults'的值没有成员'name'

下面是GameView的代码:
//
//  GameView.swift
//  Helicopter
//
//  Created by Instinct on 10/18/21.
//
import SwiftUI
import AVKit
import CoreData
struct GameView: View{
@State var audioPlayer: AVAudioPlayer!
@State private var heliPosition = CGPoint(x:100, y:100)
@State private var obstPosition = CGPoint(x:1000, y:300)
@State private var flatObstPosition = CGPoint(x:1000, y: 100)
@State var timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
@State var isPaused = false
@State private var score = 0

@Environment(.managedObjectContext) var context
//    @FetchRequest(entity: Scores.entity(), sortDescriptors: []) var scores: FetchedResults<Scores>
@State public var newScoreValue = ""
@State public var selectedScore: Scores?


let groundPosition = CGPoint(x: 0, y: 1000)
func gravity(){
withAnimation{
self.heliPosition.y += 50
}
}
func obstMove(){
if self.obstPosition.x > 0
{
withAnimation{
self.obstPosition.x -= 20

}
}
else
{
self.obstPosition.x = 1000
self.obstPosition.y = CGFloat.random(in: 0...500)
}
}
func flatObstMove(){
if self.flatObstPosition.x > 0
{
withAnimation{
self.flatObstPosition.x -= 20

}
}
else
{
self.flatObstPosition.x = 1000
self.flatObstPosition.y = CGFloat.random(in: 0...500)
}
}
func pause(){
self.timer.upstream.connect().cancel()
//        self.isPaused = true
}
func restart(){
self.timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
self.obstPosition.x = 1000
self.flatObstPosition.x = 1000
self.heliPosition = CGPoint(x:100, y:100)
self.isPaused = false
self.score = 0
}
func resume(){
self.timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
self.obstPosition.x = 1000
self.flatObstPosition.x = 1000
self.heliPosition = CGPoint(x:100, y:100)
self.isPaused = false
}
func collisionDetection(){

if abs(heliPosition.x - obstPosition.x) < (25 + 20) && abs(heliPosition.y - obstPosition.y) < (25 + 100){
pause()
self.isPaused = true
//            self.score = 0
}
if abs(heliPosition.x - flatObstPosition.x) < (25 + 150) && abs(heliPosition.y - flatObstPosition.y) < (25 + 30){
pause()
self.isPaused = true
//            self.score = 0
}
}
//    func startGame(){
//        self.timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
//        self.obstPosition.x = 1000
//        self.heliPosition = CGPoint(x:100, y:100)
//        self.isPaused = false
//        self.score = 0
//    }
func fallOffDetection(){
if abs(heliPosition.y) > 800{
pause()
self.isPaused = true
}
}
func levelDetection(){
//        if self.isPaused == true{
//            self.timer.upstream.connect().cancel()
//        }
if self.score >= abs(100){
self.timer = Timer.publish(every: 0.1, on: .main, in: .common).autoconnect()
}
else if self.score >= abs(300){
self.timer = Timer.publish(every: 0.05, on: .main, in: .common).autoconnect()
}
else{
//            Text("Level 1")
self.timer = Timer.publish(every: 0.2, on: .main, in: .common).autoconnect()
}

}

func save(scores: Scores?) {
if self.selectedScore == nil {
let newScore = Scores(context: self.context)
newScore.name = newScoreValue
try? self.context.save()
}
//            else {
//            context.performAndWait {
//                scores!.name = self.newScoreValue
//                try? context.save()
//                self.newScoreValue = ""
//                self.selectedScore = nil
//            }
//        }
}



var body: some View {



GeometryReader{ geo in

ZStack{
Helicopter()
.position(self.heliPosition)
.onReceive(self.timer){_ in
self.gravity()
//                        self.levelDetection()
}
Obstacle()
.position(self.obstPosition)
.onReceive(timer){_ in
//                        withAnimation{
self.obstMove()
//                        }
}
FlatObstacle()
.position(self.flatObstPosition)
.onReceive(timer){_ in
self.flatObstMove()
}
Ground()
.position(self.groundPosition)
self.isPaused ? HStack {
Spacer()
Button("restart"){self.restart()}.font(.system(size: 40))
Spacer()
Button("resume"){self.resume()}.font(.system(size:40))
Spacer()
Button("save score"){self.save(scores: selectedScore)}

}: nil
self.isPaused ? Text("your final score is " + String(self.score)) .position(x: geo.size.width / 2, y: geo.size.height - 700).foregroundColor(Color.white).font(.system(size: 50)): nil
TextField("(self.score)", text: $newScoreValue)
.foregroundColor(.white)
.position(x: geo.size.width - 100, y: geo.size.height / 10)
.multilineTextAlignment(.trailing)


//                    Spacer()
Ground()
//                        .frame(width: 1000, height: 200)
.foregroundColor(Color.blue)
}
//            .onAppear {
//                let sound = Bundle.main.path(forResource: "Calboy - All Night Long_2", ofType: "mp3")
//                self.audioPlayer = try! AVAudioPlayer( contentsOf: URL(fileURLWithPath: sound!))
//
//            }


//            }

.frame(width: geo.size.width, height: geo.size.height)
.background(Color.black)
.gesture(
DragGesture()
.onChanged{ value in
withAnimation{
//                        self.heliPosition.x = heliPosition.x
self.heliPosition.y = value.location.y

}

}
.onEnded{_ in
self.levelDetection()
})
//                TapGesture()
//                    .onEnded{
//                        withAnimation{
//                            self.heliPosition.y -= 100
//                        }
//                    })
//            .onReceive(self.timer){_ in
//                self.levelDetection()
//            }
}
.onReceive(self.timer) {_ in
self.collisionDetection()
self.score += 1
}
.onReceive(self.timer){_ in
self.fallOffDetection()
//                self.score = 0
}


.edgesIgnoringSafeArea(.all)

}

}

struct GameView_Previews: PreviewProvider {
static var previews: some View {
GameView()
}
}

下面是乐谱列表的代码

//
//  ViewScores.swift
//  Helicopter
//
//  Created by Instinct on 10/19/21.
//
import SwiftUI
import CoreData
struct ScoresList: View{
@Environment(.managedObjectContext) var context
@FetchRequest(entity: Scores.entity(), sortDescriptors: []) var scores: FetchedResults<Scores>
//    @State public var newScoreValue = ""
//    @State public var selectedScore: Scores?
//    @State private var newScoreValue = ""
//    @State private var selectedScore: Scores?
//    func load(scores: Scores?) {
//        if self.selectedScore == nil {
//            let newScore = Scores(context: self.context)
//            newScore.name = newScoreValue
//            try? self.context.()
//        }
var body: some View{

List{
ForEach(scores, id: .self) { score in
Text("(scores.name!)")
//                    .onTapGesture {
//                        self.newScore = savedScores.name
//                        self.selectedScore = savedScores
//                }
}
}
}

}

为了以防万一,这里是我的AppDelegate文件中的代码:

//
//  AppDelegate.swift
//  CoreDataCRUD
//
//  Created by Krassimir Iankov on 8/7/20.
//  Copyright © 2020 Krassimir Iankov. All rights reserved.
//
import UIKit
import CoreData
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return true
}
// MARK: UISceneSession Lifecycle
func application(_ application: UIApplication, configurationForConnecting connectingSceneSession: UISceneSession, options: UIScene.ConnectionOptions) -> UISceneConfiguration {
// Called when a new scene session is being created.
// Use this method to select a configuration to create the new scene with.
return UISceneConfiguration(name: "Default Configuration", sessionRole: connectingSceneSession.role)
}
func application(_ application: UIApplication, didDiscardSceneSessions sceneSessions: Set<UISceneSession>) {
// Called when the user discards a scene session.
// If any sessions were discarded while the application was not running, this will be called shortly after application:didFinishLaunchingWithOptions.
// Use this method to release any resources that were specific to the discarded scenes, as they will not return.
}
// MARK: - Core Data stack
lazy var persistentContainer: NSPersistentContainer = {
/*
The persistent container for the application. This implementation
creates and returns a container, having loaded the store for the
application to it. This property is optional since there are legitimate
error conditions that could cause the creation of the store to fail.
*/
let container = NSPersistentContainer(name: "Scores")
container.loadPersistentStores(completionHandler: { (storeDescription, error) in
if let error = error as NSError? {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

/*
Typical reasons for an error here include:
* The parent directory does not exist, cannot be created, or disallows writing.
* The persistent store is not accessible, due to permissions or data protection when the device is locked.
* The device is out of space.
* The store could not be migrated to the current model version.
Check the error message to determine what the actual problem was.
*/
fatalError("Unresolved error (error), (error.userInfo)")
}
})
return container
}()
// MARK: - Core Data Saving support
func saveContext () {
let context = persistentContainer.viewContext
if context.hasChanges {
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error (nserror), (nserror.userInfo)")
}
}
}
}

我又一次搜索了互联网和文档,但还是没有找到答案。任何帮助都非常感谢!

让您的文本使用ForEach

中的变量
Text("(score.name!)")

注意这里的单数值,复数值是数组。

最新更新