首页 > 解决方案 > SwiftUI 中数据项更改时更新列表

问题描述

ObservableObject我有一个采用协议的活动类,并有一个items数组属性,用于存储也采用的 Activity 对象ObservableObject

class Activity: ObservableObject, Codable, Identifiable {
    let id = UUID()
    @Published var title: String
    @Published var description: String
    @Published var numberOfTimesCompleted: Int = 0

    func encode(to encoder: Encoder) throws {
        var container = encoder.container(keyedBy: CodingKeys.self)

        try container.encode(title, forKey: .title)
        try container.encode(description, forKey: .description)
        try container.encode(numberOfTimesCompleted, forKey: .numberOfTimesCompleted)
    }

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

    required init(from decoder: Decoder) throws {
        let container = try decoder.container(keyedBy: CodingKeys.self)

        title = try container.decode(String.self, forKey: .title)
        description = try container.decode(String.self, forKey: .description)
        numberOfTimesCompleted = try container.decode(Int.self, forKey: .numberOfTimesCompleted)
    }
}

class Activities: ObservableObject {
    @Published var items: [Activity] {
        didSet {
            let encoder = JSONEncoder()
            if let encoded = try? encoder.encode(items) {
                UserDefaults.standard.set(encoded, forKey: "items")
            }
        }
    }

    init() {
        if let items = UserDefaults.standard.data(forKey: "items") {
            let decoder = JSONDecoder()
            if let decoded = try? decoder.decode([Activity].self, from: items) {
                self.items = decoded
                return
            }
        }

        self.items = []
    }
}

我正在使用 aList像这样动态显示我的数组

List {
  ForEach(activities.items) { activity in
    NavigationLink(destination: ActivityView(activity: activity)) {
      HStack {
        Text("\(activity.numberOfTimesCompleted)")
        VStack(alignment: .leading) {
          Text(activity.title)
          Text(activity.description)
        }
      }
    }
  }
}

当我将 Activity 传递给不同的视图(在 NavigationLink 中)并编辑numberOfTimesCompleted属性时,当我导航回列表时不会反映更改。如果我将一个新的 Activity 实例添加到列表中,列表会更新,并且新numberOfTimesCompleted值会反映在我之前编辑的 Activity 中。我感觉我很接近,但我只是在学习 Swift 和 ObservableObject,因此缺少一些东西。

标签: swiftswiftui

解决方案


这里的问题是列表视图有一个活动数组:var items: [Activity]并且孩子有一个Activity来自该数组的活动。您已经创建了活动Identifiable并且该 id 是恒定的,所以发生的情况是您从数组中传入活动并修改它,但就数组而言,没有任何改变:数组中的所有对象都具有相同的ID,所以它不会重新加载任何东西。您需要触发活动的重新加载。您可能需要考虑使用环境对象或传递一个更改闭包,该更改闭包实际上在数组上执行突变,以便重建列表视图。只有当它可以检测到发布的数组与上一个值不同时,它才会重建自己。


推荐阅读