环境对象中的SwiftUI Observable对象不会更新视图

时间:2020-07-21 18:22:15

标签: ios swift swiftui

我最近遇到一个问题,我找不到解决该问题的方法。 如果将可观察对象放置在环境对象中,则变量更改时,视图不会更新。 这是我的设置:

在SceneDelegate内部,我用environmentObject缩放了父视图:

 let parent = ParentView().environmentObject(Data())

这是环境对象:

class Data: ObservableObject {
    enum Page {
        case pageOne
    }
    var page: Page = .pageOne
    var person = Person()
}

现在我所有的视图都链接到父视图:

struct ParentView: View {

     @EnvironmentObject var data: Data

     var body: some View {
         VStack {
            if self.data.page == .pageOne {
                PageOne()
            } else {
                Text("No pages")
            }
        }
    }
}

我有一堂课(我称之为“人”):

 import Foundation
 import SwiftUI
 import Combine

 class Person: ObservableObject {

     let objectWillChange = PassthroughSubject<Person,Never>()

     @Published var age = 30 { didSet { objectWillChange.send(self)} }

     func birthday() {
         self.age += 1
         print(age)
     }

 }

这就是我的问题所在:

 struct PageOne: View {

     @EnvironmentObject var data: Data

     var body: some View {
         Text("\(data.person.age)").onTapGesture {
             self.data.person.birthday()
         }
     }
 }

当我点击文本时,此人的年龄正在增加,但视图不会更新。 我想我什至不明白为什么会这样。 我以为我知道它是如何工作的,但显然我不知道。

1 个答案:

答案 0 :(得分:2)

在您的情况下,Person不必是 class

您可以尝试以下方法:

class Data: ObservableObject {
    enum Page {
        case pageOne
    }

    var page: Page = .pageOne

    @Published var person = Person() {
        didSet {
            objectWillChange.send()
        }
    }
}
struct Person {
    var age = 30

    mutating func birthday() {
        self.age += 1
        print(age)
    }
}

如果您需要Person来继续上课,可以将其设为@Published

class Data: ObservableObject {
    enum Page {
        case pageOne
    }

    var page: Page = .pageOne
    @Published var person = Person() // <- add `@Published`
}

并从objectWillChange中删除不必要的Person代码:

class Person: ObservableObject {
    @Published var age = 30

    func birthday() {
        self.age += 1
        print(age)
    }
}

然后在Person视图中将@ObservedObject用作PageOne

struct ContentView: View {
    @EnvironmentObject var data: Data

    var body: some View {
        VStack {
            if self.data.page == .pageOne {
                PageOne(person: data.person) // pass `person` object
            } else {
                Text("No pages")
            }
        }
    }
}

struct PageOne: View {
    @ObservedObject var person: Person // observe `person` directly

    var body: some View {
        Text("\(person.age)").onTapGesture {
            self.person.birthday()
        }
    }
}