У меня есть сущность Урока, хранящаяся в Базовых данных, одна из переменных которой - хранить, завершен ли урок.
Уроки перечислены в списке SwiftUI и при выборе go к Виду, где существует игра. Как только игра завершена, переменная complete обновляется до true. И что должно произойти, так это то, что в представлении списка отображается игра в списке с галочкой рядом с игрой.
Однако, что происходит, когда я сохраняю «законченное» состояние урока в игре (в методе tapRight - см. Ниже), я получаю предупреждение:
[TableView ] Только одно предупреждение: UITableView было приказано расположить свои видимые ячейки и другое содержимое, не находясь в иерархии представлений (табличное представление или одно из его суперпредставлений не было добавлено в окно).
А потом, когда я вернуться к списку просмотра, нажав кнопку навигации вверху игры. Вид, я обнаружил, что игра исчезла из списка.
Однако, когда я закрываю приложение и снова открываю его, появляется список со строкой для игры и галочкой, поэтому я знаю, что экземпляр урока основных данных обновляется правильно. Код для просмотра списка ниже.
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()
}
}
Соответствующий код в игре Просмотр для сохранения завершенного статуса:
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
}
}
Код для lessonRow выглядит следующим образом :
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
- Настройка урока NSManagedObject с помощью функции setComplete, который вызывает 'objectWillChange'
- Делая @FetchRequest более подробным, добавив true и false для полной переменной
Буду признателен за любые предложения, как решить эту проблему. Я новичок в SwiftUI, поэтому заранее спасибо за вашу помощь.