【问题标题】:How to use BindableObjects (EnviromentObject)?如何使用可绑定对象(EnvironmentObject)?
【发布时间】:2019-10-23 07:19:18
【问题描述】:

我正在使用新的 SwiftUI。我有一个UserUpdate 类,它是一个Bindable Object,我想修改这些变量并自动更新用户界面。

我成功更新了这些值,但是当我更改 UserUpdate 类中的变量时,我的 UI 结构中的视图没有更新。

在我修改 UI 结构本身中的 @EnviromentObject 变量时发生变化。

这是我的可绑定对象类:

final class UserUpdate: BindableObject {
    let didChange = PassthroughSubject<Any, Never>()

    var allUsers: [User] = [] {
        didSet {
            print(allUsers)
            didChange.send(allUsers)
        }
    }

    var firstName: String = "" {
        didSet {
            didChange.send(firstName)
        }
    }

    var lastName: String = "" {
        didSet {
            didChange.send(lastName)
        }
    }
}

这是我的用户类:

struct User: Identifiable {
    let id: Int
    let firstName, lastName: String
}

以下是我配置 UI 的方式:

struct ContentView : View {
    @EnvironmentObject var bindableUser: UserUpdate

    var body: some View {
        NavigationView {
            VStack(alignment: .leading) {
                Text("All Users:").bold().padding(.leading, 10)
                List {
                    ForEach(bindableUser.allUsers) { user in
                        Text("\(user.firstName) \(user.lastName)")
                    }
                }
            }
        }
    }
}

这里我修改UserUpdate中的变量:

class TestBind {
    static let instance = TestBind()

    let userUpdate = UserUpdate()

    func bind() {
        let user = User(id: userUpdate.allUsers.count, firstName: "Heyy", lastName: "worked")
        userUpdate.allUsers.append(user)
    }
}

【问题讨论】:

  • 那是因为你的视图变量(bindableUser) 绑定到EnvirnomentObject 流。视图不会知道您是否更新了其他流。
  • 我该如何解决呢?我不明白为什么 Bindable Object 有用。
  • 您是否已将环境绑定到场景委托中的视图?见stackoverflow.com/questions/56476007/…
  • @Paulw11 我已经这样做了
  • BindableObject 协议现在重命名为 ObservableObjectObjectBinding 现在是 ObservedObjectdidChange 现在是 objectWillChange

标签: ios swift swiftui


【解决方案1】:

我发现我必须从我的 UI 中调用该方法才能使其工作,以便它在同一个流上。

例如这样:

struct ContentView : View {
@EnvironmentObject var networkManager: NetworkManager

var body: some View {
    VStack {
        Button(action: {
            self.networkManager.getAllCourses()
        }, label: {
            Text("Get All Courses")
        })

        List(networkManager.courses.identified(by: \.name)) {
            Text($0.name)
        }
    }
}
}

【讨论】:

    【解决方案2】:

    如果我没记错的话,你应该在你的ContentView 中注入UserUpdate 实例,可能在SceneDelegate 中,使用ContentView().environmentObject(UserUpdate())

    在这种情况下,您有 2 个不同的 UserUpdate 类实例,第一个在 SceneDelegate 中创建,第二个在 TestBind 类中创建。

    问题是您有一个与视图绑定的实例(并且会在更新时触发视图重新加载),而您实际修改的一个实例(在TestBind 类中)与视图完全无关。

    您应该找到一种在视图和TestBind 类中使用相同实例的方法(例如使用ContentView().environmentObject(TestBind.instance.userUpdate)

    【讨论】:

      猜你喜欢
      • 2015-09-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2015-04-22
      • 2012-02-29
      相关资源
      最近更新 更多