gpt4 book ai didi

在另一个 View 中更新核心数据实体后,SwiftUI ListView 未更新

转载 作者:行者123 更新时间:2023-12-04 01:32:04 26 4
gpt4 key购买 nike

我有一个存储在 Core Data 中的 Lesson 实体,其变量之一是存储类(class)是否完成。

类(class)列在 SwiftUI 列表中,选择后转到游戏所在的 View 。一旦游戏完成,完整变量将更新为真。应该发生的是 ListView 显示列出的游戏,并在游戏旁边带有复选标记。

然而,发生的事情是,当我在游戏中保存类(class)的“完成”状态时(在 tapRight 方法中 - 见下文),我收到警告:

[TableView] 仅警告一次:UITableView 被告知在不在 View 层次结构中布局其可见单元格和其他内容(表 View 或其超 View 之一尚未添加到窗口中)。

然后当我通过按下游戏 View 顶部的导航按钮返回 ListView 时,我发现游戏已经从列表中消失了。

但是,当我关闭应用程序并重新打开它时,列表中包含游戏行和复选标记,因此我知道核心数据类(class)实例正在正确更新。下面 ListView 的代码。

import SwiftUI
import CoreData
import UIKit

struct LessonList: View {

@Environment(\.managedObjectContext) var moc

@State private var refreshing = false
private var didSave = NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave)

@FetchRequest(entity: Lesson.entity(), sortDescriptors: [], predicate: NSPredicate(format: "(type == %@) AND (stage == %@) AND ((complete == %@) OR (complete == %@))", "phonicIntro", "1", NSNumber(value: true), NSNumber(value: false) )) var phonicIntroLessons1: FetchedResults<Lesson>

var body: some View {

NavigationView {
List {
self.stage1Section
}
.navigationBarTitle("Lessons")
}
}


private var phonicIntroLink : some View {
ForEach(phonicIntroLessons1) { lesson in
NavigationLink(destination: PhonicIntroGame(lesson: lesson)) {
LessonRow(lesson: lesson)
}
}
}

private var stage1Section : some View {
Section(header: Text("Stage 1")) {
phonicIntroLink
}.onReceive(self.didSave) { _ in
self.refreshing.toggle()
}
}

游戏 View 中保存完成状态的相关代码:
import SwiftUI
import AVFoundation

struct PhonicIntroGame: View {

@Environment(\.managedObjectContext) var moc

var lesson: Lesson?

func tapRight() {
if ((self.lesson?.phonicsArray.count ?? 1) - 1) > self.index {
self.index = self.index + 1
print("This is index \(self.index)")
//On completion
if (index + 1) == (lesson!.phonicsArray.count) {
self.lessonComplete()
}
} else {
print(self.index)

func lessonComplete() {
self.lesson?.setComplete(true)
self.saveLesson()
}

func saveLesson() {
do {
try moc.save()
} catch {
print("Error saving context \(error)")
}
}

在 NSManagedObject 子类中:
extension Lesson {

func setComplete (_ state: Bool) {
objectWillChange.send()
self.complete = state
}
}

LessRow 的代码如下:
import SwiftUI
import CoreData

struct LessonRow: View {

@Environment(\.managedObjectContext) var moc
@State var refreshing1 = false
var didSave = NotificationCenter.default.publisher(for: .NSManagedObjectContextDidSave)
var lesson: Lesson

var body: some View {
HStack {
Image(lesson.wrappedLessonImage )
.resizable()
.frame(width: 80, height: 80)
.cornerRadius(20)

Text(lesson.wrappedTitle)
.font(.system(size: 20))
.fontWeight(.thin)
.padding()

if lesson.complete == true {
Image(systemName: "checkmark.circle")
.resizable()
.frame(width: 30, height: 30)
.foregroundColor(.green)
} else {
Rectangle()
.frame(width: 30, height: 30)
.foregroundColor(.clear)
}
}.padding()
.onReceive(self.didSave) { _ in
self.refreshing1.toggle()
}


}
}

我尝试过的事情:
  • 强制列表重新加载通知和 .onReceive
  • 使用 setComplete 函数设置 Lesson NSManagedObject 子类,该函数调用“objectWillChange”
  • 通过为完整变量
  • 包含 true 和 false 使 @FetchRequest 更加详细

    对于如何解决此问题的任何建议,我将不胜感激。我是 SwiftUI 的新手,所以提前感谢您的所有帮助。

    最佳答案

    是的,我最终解决这个问题的方法是将 @ObservedObject 添加到 PhonicIntroGame : View 中的存储对象。如下 -

    @ObservedObject var lesson: Lesson

    关于在另一个 View 中更新核心数据实体后,SwiftUI ListView 未更新,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/60750558/

    26 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com