我正在try 使用快速用户界面从核心数据中保存和获取数据.我调试了代码,我可以看到数据被保存到核心数据中,它有5条记录,但问题是当我试图重新加载和重新运行它时,它只显示了一条记录.

以下是代码视图模型.

import Foundation
import CoreData

@MainActor
class RedditViewModel: ObservableObject {

    @Published private(set) var stories = [Story]()


    private var redditService: RedditService

    init(redditService: RedditService = RedditService()) {
        self.redditService = redditService
    }

    // Swift 5.5
    func fetchData(viewContext: NSManagedObjectContext) async {
        let url = NetworkURLs.urlBase
        do {
            let response = try await redditService.getModel(from: url)
            let stories = response.data.children.map { $0.data }
            self.stories = stories
            saveRecord(viewContext: viewContext)

        } catch (let error) {
            print(error)
        }
    }
    public func saveRecord(viewContext: NSManagedObjectContext) {

        do {
            let redit = ReditEntity(context: viewContext)
            stories.forEach { story in
                redit.title = story.title
                redit.numComments = Int64(story.numComments)
                redit.score = Int64(story.score)
                redit.urlImage = story.thumbnail

            }
            try viewContext.save()
        } catch {
            print(error.localizedDescription)
        }

    }
}

以下是Main应用程序的代码.

import SwiftUI

@main
struct CoreDataDemoApp: App {

   @StateObject private var viewModel = RedditViewModel()
   let persistentContainer = CoreDataManager.shared.persistentContainer

    var body: some Scene {
        WindowGroup {
            ContentView().environment(\.managedObjectContext, persistentContainer.viewContext).environmentObject(viewModel)
        }
    }
}

以下是内容视图中的代码.

import SwiftUI
import CoreData

struct ContentView: View {

    @EnvironmentObject private var viewModel: RedditViewModel
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(entity: ReditEntity.entity(), sortDescriptors: [])
    private var dbStories: FetchedResults<ReditEntity>
    var dbFatchReditRecord: NSFetchRequest<ReditEntity> = ReditEntity.fetchRequest()


    var body: some View {

        VStack {
            Text("Reddit Service")
                .font(.largeTitle)
            List {
                ForEach(dbStories) { story in
                    // custom cell
                    RowView(title: story.title ?? "", comments: "\(story.numComments)", score: "\(story.score)", urlImage: story.urlImage)
                }
            }
        }
        .onAppear {
            if dbStories.isEmpty {

                Task {
                    await viewModel.fetchData(viewContext: viewContext)

                }
            }
        }

    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        let persistedContainer = CoreDataManager.shared.persistentContainer
        ContentView().environment(\.managedObjectContext, persistedContainer.viewContext)    }
}

以下是RowView.swft的代码

import SwiftUI

struct RowView: View {

    @EnvironmentObject var viewModel: RedditViewModel

    let title: String
    let comments: String
    let score: String
    let urlImage: String?

    var body: some View {
        VStack(alignment: .leading) {
            HStack {
                if let urlImage = urlImage, urlImage.contains("https"), let url = URL(string: urlImage) {
                    AsyncImage(url: url)
                }
                VStack(alignment: .leading) {
                    HeadTitleView(title: title)
                    Text("Comments: \(comments)")
                    Text("Score: \(score)")
                    Spacer()
                }
            }

        }
    }
}

这是Header.swft的代码.

import SwiftUI

struct HeadTitleView: View {

    @EnvironmentObject var viewModel: RedditViewModel
    let title: String

    var body: some View {
        Text(title)
    }
}

这是截图.

enter image description here

推荐答案

let redit = ReditEntity(context: viewContext)
stories.forEach { story in
    redit.title = story.title
    ...
}

在这里,您正在创建一个Entity对象,但是您随后在循环中重用了相同的对象,因此您最终要做的是用每个故事更新这个单个对象,而不是 for each 故事创建一个新对象.

只需交换线路即可解决问题

stories.forEach { story in
    let redit = ReditEntity(context: viewContext)
    redit.title = story.title
    ...
}

Swift相关问答推荐

启用完整并发判断以及如何解决警告

Swift UI在视图中排序不同的 struct

RealityKit(VisionOS)中的PhysicBodyComponent和DragGesture

在SwiftUI中使用自定义图像填充列表行的正确方法

带DispatchSourceTimer的定时器

仅当单击UIButton时才调用计时器函数

使 tabview 垂直将视图移动到右侧 swift ui

表视图插座单元测试失败

为什么变量不存储在 Swift 的过程数据区中

swift 是否遇到 Java 的 2gb 最大序列化大小问题?

Swift 非参与者隔离闭包

单击按钮后的计时器发布者初始化计时器

在 RealityKit 中创建转场

swift中的SequenceType和CollectionType有什么区别?

iOS Swift - 如何更改表格视图的背景 colored颜色 ?

AES 加密和解密

NSFontAttributeName 已更改为 String

在 Swift 中获取双精度的小数部分

Swift performSegueWithIdentifier 不起作用

对分段控制的快速处理动作