我们如何才能通知ObservableObject有关其初始化程序的更改?

时间:2020-11-04 04:57:24

标签: swift swiftui

我有一个ObservableObject-Class,在该类中,我得到了一个名为 persons 的已发布变量!我确实使用一些名为 allData 的数据对其进行了初始化。

然后,我尝试使用按钮操作更新 allData ,此操作将所需的更新应用于我的 allData ,但是我发布的var不知道此数据已更新!

如何使发布的内容能够看到新的更新的 allData

struct PersonData: Identifiable {
    let id = UUID()
    var name: String
}

var allData = [PersonData(name: "Bob"), PersonData(name: "Nik"), PersonData(name: "Tak"), PersonData(name: "Sed"), PersonData(name: "Ted")]

class PersonDataModel: ObservableObject {
    @Published var persones: [PersonData] = allData
}

struct ContentView: View {
    @StateObject var personDataModel = PersonDataModel()

    var body: some View {
        VStack
        {
            Button("update allData") { allData = [PersonData(name: "Bob")] }

            HStack
            {
                ForEach(personDataModel.persones) { person in Text(person.name) }
            }
        }
        .font(Font.title)
    }
}

PS:我不想为此使用.onChange或其他东西,我希望这在我的班级内部发生。

我也知道我可以使用下来的代码来完成这项工作,但这不是答案

personDataModel.persones = [PersonData(name: "Bob")] 

3 个答案:

答案 0 :(得分:1)

拥有一个顶级属性(在任何类或结构之外)可能不是一个好主意。我看不到全部图片,但看来您的应用需要全局状态(例如,在@StateObject级别初始化的App)。考虑以下答案:


如果您确实需要观察数组,则需要使其成为 observable

一种选择是使用Combine框架中的CurrentValueSubject

var persons = ["Bob", "Nik", "Tak", "Sed", "Ted"].map(PersonData.init)
var allData = CurrentValueSubject<[PersonData], Never>(persons)

class PersonDataModel: ObservableObject {
    @Published var persones: [PersonData] = allData.value

    private var cancellables = Set<AnyCancellable>()

    init() {
        allData
            .sink { [weak self] in
                self?.persones = $0
            }
            .store(in: &cancellables)
    }
}

struct ContentView: View {
    @StateObject var personDataModel = PersonDataModel()

    var body: some View {
        VStack {
            Button("update allData") { 
                allData.send([PersonData(name: "Bob")]) 
            }
            HStack {
                ForEach(personDataModel.persones) { person in 
                    Text(person.name)
                }
            }
        }
        .font(Font.title)
    }
}

答案 1 :(得分:0)

allData在初始化时被复制到persones中,因此之后对其进行更改对personDataModel无效。创建StateObject之后,您必须像

Button("update allData") { 
   self.personDataModel.persones = [PersonData(name: "Bob")] 
}

答案 2 :(得分:0)

我认为您做错了事。

如果要更新所有视图,则必须使用@EnviromentObject传递同一对象。

我不知道您的存储方法(JSON,CORE DATA,iCloud),但是正确的方法是直接更新模型

class PersonDataModel: ObservableObject
{
    @Published var persones: [PersonData] = loadFromJSON //one func that is loading your object stored as JSON file

    func updateAllData() {
        storeToJSON(persones) //one func that is storing your object as JSON file
    }
}


struct ContentView: View {
    
    @StateObject var personDataModel = PersonDataModel()
    
    var body: some View {

        VStack
        {
            Button("update allData") { 
                self.personDataModel.persones = [PersonData(name: "Bob")] 
             }
            
            
            HStack
            {
                ForEach(personDataModel.persones) { person in Text(person.name) }
            }


 
        }
        .font(Font.title)
        .onChange($personDataModel.persones) {
             persones.updateAllData()
        }
    }
}