【问题标题】:ListView not updating after item class is modified in swiftui在swiftui中修改项目类后ListView不更新
【发布时间】:2021-11-03 10:04:53
【问题描述】:

我有一个任务项目的列表视图。每 10 秒一个计时器触发函数 randomTasks 负责修改列表中每个任务的标题和描述,但 ListView 不反映更改。我尝试使用 objectWillChange.send() 但它不起作用.

我注意到,当使用不同的 id 修改任务时,ListView 会更新,我可以看到更改,但是当我在详细视图中时,只要触发 randomTaskTitle,视图就会自动关闭。

class Task {
    var id: String = UUID().uuidString
    var title: String
    var description: String

    init(title: String, description: String) {
        self.title = title
        self.description = description
    }
}

import SwiftUI

struct TasksView: View {
    
    @EnvironmentObject var viewModel: TasksViewModel

        let timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect()
    
    var body: some View {
        
        NavigationView {
          List {
            ForEach(viewModel.tasks, id: \.id) { task in          
               NavigationLink(
                  destination: DetailView(task: task)
               ) {
                  VStack {
                    Text(task.title)
                    Text(task.description)
                  }
               }
          }
        }
        .onReceive(timer) { time in
            Task {
                await viewModel.randomTasks()
            }
        }
        
    }
}

struct TasksViewNew_Previews: PreviewProvider {
    static var previews: some View {
        TasksView()
    }
}
import Foundation

@MainActor
class TasksViewModel: ObservableObject {

    @Published var tasks = [Task]()

    init() {
      self.tasks = [Task(title: "TaskA", description: "DescriptionA"),
                    Task(title: "TaskB", description: "DescriptionB"),
                    Task(title: "TaskC", description: "DescriptionC"),
                    Task(title: "TaskD", description: "DescriptionD"),]
    }
    
    func randomTasks() {
      tasks.forEach { task in
        task.title = randomTitleTask()
        task.description = randomDescriptionTask()
      }
    }
    
}

【问题讨论】:

标签: swift swiftui


【解决方案1】:

试试这样简单的东西,对我很有效:

@MainActor
class TasksViewModel: ObservableObject {
    
    @Published var tasks = [Task]()
    
    init() {
        self.tasks = [Task(title: "TaskA", description: "DescriptionA"),
                      Task(title: "TaskB", description: "DescriptionB"),
                      Task(title: "TaskC", description: "DescriptionC"),
                      Task(title: "TaskD", description: "DescriptionD"),]
    }
    
    func randomTasks() {
        tasks.forEach { task in
            task.title = randomTitleTask()
            task.description = randomDescriptionTask()
        }
        objectWillChange.send()   // <--- here
    }
}

struct TasksView: View {
    @EnvironmentObject var viewModel: TasksViewModel
    let timer = Timer.publish(every: 10, on: .main, in: .common).autoconnect()
    
    var body: some View {
        NavigationView {
            List {
                ForEach(viewModel.tasks, id: \.id) { task in
                    NavigationLink(destination: DetailView(task: task)) {
                        VStack {
                            Text(task.title)
                            Text(task.description)
                        }
                    }
                }
            }
            .onReceive(timer) { time in
                // no need for Task here since randomTasks is not an async
                viewModel.randomTasks()  // <--- here
            }
        }
    }
}

【讨论】:

  • 我相信你应该在tasks.forEach ...之前有objectWillChange.send()
  • 是的,你可以把它放在前面。在我的基本测试中,它似乎也能正常工作。
【解决方案2】:

类中的@Published 数组不知道您的对象何时更改。它只能跟踪您添加/删除它们的时间。

  1. 您可以通过在修改前调用 objectWillChange.send() 来告诉您的 ObservableObject 某些内容已明确更改
objectWillChange.send()
tasks.forEach { task in
    task.title = UUID().uuidString
    task.description = UUID().uuidString
}
  1. 将您的类转换为结构,并按索引更改项目,例如
tasks.indices { i in
    tasks[i].title = UUID().uuidString
    tasks[i].description = UUID().uuidString
}
  1. this answer 签出ObservableArray

【讨论】:

    【解决方案3】:

    使用@StateObject 代替@ObservedObject

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-09-24
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-01-28
      • 2013-03-06
      • 2023-04-11
      相关资源
      最近更新 更多