- html - 出于某种原因,IE8 对我的 Sass 文件中继承的 html5 CSS 不友好?
- JMeter 在响应断言中使用 span 标签的问题
- html - 在 :hover and :active? 上具有不同效果的 CSS 动画
- html - 相对于居中的 html 内容固定的 CSS 重复背景?
我正在学习 SwiftUI 并修改了一个现有示例,因为我想测试是否可以跨 View 访问 ObservableObject。在阅读文档时,我发现我应该为此使用@EnvironmentObject。我试过了,但这不起作用:数组 persons 充满了新人(使用调试器)但 UI 没有更新。如果我在 @EnvironmentObject 之外使用 people 属性,它会按预期工作。
我的代码:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var envTest: EnvTest
var body: some View {
VStack {
ForEach(envTest.people.persons) { person in
Text("\(person.name)")
}
Button(action: {
self.envTest.people.persons.append(Person(id: 4, name: "I am new here"))
}) {
Text("Add/Change name")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static let envTest = EnvTest()
static var previews: some View {
ContentView().environmentObject(envTest)
}
}
class Person: ObservableObject, Identifiable {
var id: Int
@Published var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
}
class People: ObservableObject {
@Published var persons: [Person]
init() {
self.persons = [
Person(id: 1, name: "Jabba"),
Person(id: 2, name: "Polke"),
Person(id: 3, name: "Lori")]
}
}
class EnvTest: ObservableObject {
@ObservedObject var people = People()
}
我使用以下方法将 EnvTest 添加到 SceneDelegate:
var window: UIWindow?
var envTest = EnvTest()
func scene(...) {
let contentView = ContentView().environment(\.managedObjectContext, context).environmentObject(envTest)
}
最佳答案
要获得您想要的结果,需要解决两个问题:
Combine
并将 EnvTest
中的 @ObservedObject
替换为 @Published
people
属性的 objectWillChange
添加订阅者,在“people”属性更改时手动触发 EnvTest.objectWillChange
。这两个更改的原因与 ObservableObject
的工作方式有关。 documentation告诉我们
An ObservableObject synthesizes an
objectWillChange
publisher that emits the changed value before any of its @Published properties changes.
如果您没有 @Published
属性,则 People.objectWillChange
发布者将不会发出任何内容。一旦我们解决了这个问题,当我们更改 People
上的 persons
属性时,会触发 People.objectWillChange
发布者发出一个值。然而,第二个问题暴露了,SwiftUI 正在监听 EnvTest.objectWillChange
发布者,所以我们看不到 UI 更新。这就是为什么当我们收到来自 People.objectWillChange
发布者的值时,我们必须在 EnvTest.objectWillChange
发布者上手动调用 send
以通知SwiftUI 它需要生成新的 View 。
当您将 @Published
属性包装器放在符合 ObservableObject
的类型的属性上时,如果 Combine 自动传播 objectWillChange
调用就好了>。类似地,如果 SwiftUI 观看最低级的 ObservableObject
而不是顶级的(即在这种情况下观看 People
而不是 EnvTest
),那就太好了.也许这会在未来引入,因为当前手动链接两者的解决方案很痛苦,而且无法很好地扩展。
完成您想要的代码的完整解决方案是:
import SwiftUI
import Combine
struct ContentView: View {
@EnvironmentObject var envTest: EnvTest
var body: some View {
VStack {
ForEach(envTest.people.persons) { person in
Text("\(person.name)")
}
Button(action: {
self.envTest.people.persons.append(Person(id: 4, name: "I am new here"))
}) {
Text("Add/Change name")
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static let envTest = EnvTest()
static var previews: some View {
ContentView().environmentObject(envTest)
}
}
class Person: ObservableObject, Identifiable {
var id: Int
@Published var name: String
init(id: Int, name: String) {
self.id = id
self.name = name
}
}
class People: ObservableObject {
@Published var persons: [Person]
init() {
self.persons = [
Person(id: 1, name: "Jabba"),
Person(id: 2, name: "Polke"),
Person(id: 3, name: "Lori")]
}
}
class EnvTest: ObservableObject {
@Published var people = People()
init(people: People = People()) {
self.people = people
people.objectWillChange.receive(subscriber: Subscribers.Sink(receiveCompletion: { _ in }) {
self.objectWillChange.send()
})
}
}
关于swift - 为什么嵌入在 EnvironmentObject 中的 ObservableObject 不向列表中添加新项目,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59274736/
我有一个名为 PurchaseView 的 View .此 View 显示有关购买、购买的内容和购买者的详细信息。我正在做的是,在这个 View 中,我同时放置了 ItemView和 ClientVi
public typealias ObservableObject = ObservableObject 为什么这个看似毫无意义的类型别名在这里? 最佳答案 您可以在 swift-corelibs-f
我有一个可以保存图像的游戏对象。每当找到游戏的图像 URL 时,就应该创建一个新的 GameImage 对象实例。然后它将获取图像并填充 UIImage 属性。发生这种情况时,应更新 UI 以显示图像
使用 SwiftUI 我想按下一个按钮并让它切换用于过滤图像的类。 在 SwiftUI 中,按钮会执行如下操作: @ObservedObject var currentFilter = FilterC
问题 为了实现应用程序代码的简洁外观,我为每个包含逻辑的 View 创建了 ViewModel。 一个普通的 ViewModel 看起来有点像这样: class SomeViewModel: Obse
我有一个设置为 ObservableObject 的类: class MatchData : Identifiable, ObservableObject { @Published
好的,SwiftUI 和 ObservableObject,在 iOS 13 上。我有 Model 实现了 ObservableObject: class Model: ObservableObjec
我有一个类Foo对 ObservableObject 具有多个依赖项.出于测试目的,我想创建这些对象的模拟版本,但我看不到这样做的方法,然后将它们注入(inject) Foo . 我无法创建另一个协议
我想在 SwiftUI 中有一个可选的 @ObservedObject 但我一直收到编译时错误。 Property type 'AModel?' does not match that of the
我有一个 ObservableObject class CurrentPosition: ObservableObject { @Published var northEast = CLLoc
我在 View 中创建了一个 ObservableObject。 @ObservedObject var selectionModel = FilterSelectionModel() 我在 Filt
class Group: ObservableObject { @Published var size: CGFloat = 22 } struct content: View { @
我对 SwiftUI 很陌生(而且我也有一段时间没有接触过 Swift)所以请耐心等待: 我有这样的看法: import SwiftUI import Combine var settings = U
当 SwiftUI View 绑定(bind)到 ObservableObject 时,当被观察对象发生任何变化时, View 会自动重新加载 - 无论是否更改直接影响 View 。 这似乎会给非平凡
我想在 ObservableObject 中导入一个实际的变量集: 我的代码是: import SwiftUI struct HomepageView: View { @ObservedOb
请帮助我理解 MVVM 模式中的一件事: 例如,我需要在 map 上显示城市。在 ViewModel 中,我有 ObservableCollection,它绑定(bind)到 View ItemsSo
我在我的 DateView 中有一个这样声明的 ObservableObject: import SwiftUI class SelectedDate: ObservableObject {
我尝试使 NWPathMonitor 成为一个可观察对象,如果有网络连接则返回 true,否则返回 false。 你能帮我吗,因为我的解决方案不起作用。 谢谢 import Foundation im
我正在尝试学习与 SwiftUI 结合,我正在努力如何使用 ObservableObject 更新我的 View (来自 UIKit) (以前的 BindableObject )。显然,问题是方法 u
我有一个 SwiftUI 项目和一个绑定(bind)到 EnvironmentObject 的 View 。该对象包含一个@Published 属性。 import Foundation class
我是一名优秀的程序员,十分优秀!