如何在SwiftUI中观察数组的单个元素

时间:2019-10-11 15:13:55

标签: swift swiftui

假设我有一个Employee类,可以观察其图片属性。

internal class Employee: CustomDebugStringConvertible, Identifiable, ObservableObject {
    internal let name: String
    internal let role: Role
    @Published internal var picture: UIImage?
}

带有一个存储一组雇员的类。此数组可能稍后会发生突变,因此它是一个@Published属性:

internal class EmployeeStorage: ObservableObject {
    @Published internal private(set) var employees: [Employee]
}

现在,我有一个使用员工存储的视图列表:

struct EmployeeList: View {
    @ObservedObject var employeeStorage = EmployeeStorage.sharedInstance

    var body: some View {
        // Uses employeeStorage.employee property to draw itself
    }
}

该列表用于内容视图:

struct ContentView: View {
    @ObservedObject var employeeStorage = EmployeeStorage.sharedInstance

    var body: some View {
        // Uses an EmployeeList value
    }
}

比方说,现在EmployeeStorage对象发生了变化,从而使雇员数组发生了变化:这有效地更新了UI,我可以看到该列表已使用新的雇员集合进行了更新。问题:当员工的图片属性更改时,如果我想获得相同的效果怎么办?我以为这足够了,但就我而言(我有一个更复杂的示例),如果员工的图像发生更改,则不会更新UI。怎么做?

1 个答案:

答案 0 :(得分:1)

您的代码中有几个问题。

  • Employee模型

    • 您的模型应为结构。
    • 它不需要符合ObservableObject
    • 为什么要使用UIImage !?如果您要从Web Api异步获取数据,只需使用Image,甚至可以使用URL。
    • 类似的东西

    // Employee Model
    struct Employee: Codable, Identifiable {
        let name: String
        let role: Role
        let imageUrl: String
        let picture: Image
    }
    
  • EmployeeStorage

    • 我怀疑您将EmployeeStorage用作单例的方式存在问题。 Apple建议您最好使用@EnvironmentObject属性传递视图及其子视图之间共享的数据。超级简单,但功能强大!

话虽如此,您可以按以下方式修改代码:

// Employees Store
final class EmployeeStorage: ObservableObject {
    @Published var employees: [Employee]
}

// Content View
struct ContentView: View {
    var employeeStorage = EmployeeStorage()

    var body: some View {
        ...
        EmployeeList()
        .environmentObject(employeeStorage) // here you pass the storage to the list
    }
}

// Employee List
struct EmployeeList: View {
    @EnvironmentObject var employeeStorage: EmployeeStorage

    var body: some View {
        NavigationView {
            List {
                ForEach(employeeStorage.employees) { employee in
                        NavigationLink(
                            destination: EmployeeDetail()
                                .environmentObject(employeeStorage) 
                        ) {
                            EmployeeRow(employee: employee)
                        }
                }.navigationBarTitle(Text("Employees"))
            }
        }
    }
}

有关更多信息,您可以签出this。已经完成了您将要达到的目标。