【问题标题】:SwiftUI and FetchRequest : delay the reordering of a listSwiftUI 和 FetchRequest :延迟列表的重新排序
【发布时间】:2020-09-19 04:55:36
【问题描述】:

我编写了一个显示学生列表的应用程序。为此,我使用了NavigationLinkList。学生按其属性questionAskedClass 之一排序,这是一个整数。所有这些信息都存储在 CoreData 中。

@Environment(\.managedObjectContext) var managedObjectContext
@FetchRequest(entity: Student.entity(),
    sortDescriptors: [NSSortDescriptor(keyPath: \Student.questionAskedClass,
                                       ascending: true)])
var students: FetchedResults<Student>

var body: some View {
  NavigationView {
    List {
      ForEach(students) {student in
        NavigationLink(destination: StudentView(student: student)) {
          HStack {
            VStack(alignment: .leading) {
              Text("\(student.firstName)").font(.headline).foregroundColor(Color.black)
              Text("\(student.lastName)").font(.headline).foregroundColor(Color.gray)
            }
          }
        }
      }
    }
  }
}

当我按下学生的姓名时,我会切换到一个名为StudentView 的新视图,在该视图中我可以获取有关该学生的更多信息以及可以在其中更新属性questionAskedClass

struct StudentView: View {
  @Environment(\.managedObjectContext) var managedObjectContext


  func askQuestion() {
    self.managedObjectContext.performAndWait {
      self.student.questionAskedClass += 1
      try? self.managedObjectContext.save()
    }
  }
}

不幸的是,当我更改该属性时,初始列表的顺序发生了变化,我被带离了StudentView。框架似乎感觉到列表需要重新排序。但我只希望在返回列表时重新排序此列表。当我更改 questionAskedClass 的值时不会立即发生。

我可以做些什么来缓解这个问题?

感谢您的帮助。

【问题讨论】:

    标签: core-data swiftui


    【解决方案1】:

    您可以尝试创建一个简单的NSFetchRequest&lt;Student&gt; 并使用此获取的结果来更新您的学生列表。

    @State var students: [Student] = []
    
    fun refresh() {
        let fetchRequest = NSFetchRequest<Student>(entityName: "Student")
        students = try? managedObjectContext.fetch(fetchRequest) ?? []
    }
    

    您可以在onAppear 中触发此refresh,这样每次View 出现时列表都会更新:

    NavigationView {
        ...
    }.onAppear {
        self.refresh()
    }
    

    或者,您可以将上下文保存在主视图的onAppear 中,而不是StudentView

    struct StudentView: View {
        func askQuestion() {
            self.student.questionAskedClass += 1
        }
    }
    
    NavigationView {
        ...
    }.onAppear {
        try? self.managedObjectContext.save()
    }
    

    如果您希望您的数据在应用程序终止时保持不变,请在 AppDelegate 中添加此函数(假设您的 persistentContainer 在那里声明:

    func applicationWillTerminate(_ application: UIApplication) {
        try? persistentContainer.viewContext.save()
    }
    

    【讨论】:

    • 对不起。我对 Apple/Swift 很陌生。我应该在StudentView 中声明var workingContext 吗?我应该在askQuestion 函数中同时保存workingContextmanagedObjectContext 吗?
    • 我现在意识到你只想在View 中做所有事情。我已经更新了我的答案。通常人们会遇到问题View 并不令人耳目一新:link
    • 感谢您的帮助。我已将 FetchRequest 替换为 @FetchRequest(entity: Student.entity(), sortDescriptors: []) 并将 ForEach 替换为 ForEach(students.sorted { $0.questionAskedClass &lt; $1.questionAskedClass })(我想这就是您的意思),但 FetchRequest 仍然在 StudentView 内触发。
    • 到目前为止,我得到的最好的方法是在StudentView 中创建一个局部变量,该变量在视图出现时从CoreData 存储questionAskedClass,并在视图消失时将其保存回来。但是如果我们在StudentView 内退出应用程序,它不会被保存回来。
    • 我认为使用@FetchRequest 的全部意义在于您的students 变量与核心数据中的内容保持同步。当您更改一些student 时,它会强制重绘您的学生列表视图。要绕过自动刷新,您可以尝试创建一个简单的获取请求 NSFetchRequest&lt;Student&gt; 并在 onAppear 中触发它。
    猜你喜欢
    • 2020-11-05
    • 2022-07-01
    • 1970-01-01
    • 1970-01-01
    • 2020-12-13
    • 1970-01-01
    • 2020-07-15
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多