Combine 是否有仅在值实际发生变化时才发布的发布者?

时间:2021-01-26 16:58:25

标签: swiftui combine

有没有办法让 @Published 变量仅在新值与旧值不同时才发布其值?

现在如果我们有

@Published var test: Bool = false

我们这样做

test = false
test = false
test = false

发布者被调用了 3 次。这很烦人,因为它有时会导致我的 SwiftUI 视图被重新创建,因为在层次结构中较高的某个地方,发布者被设置为之前设置的值,通过另一个被触发的发布者(并且破坏了文本字段输入,因为视图模型通过发生这种情况时会重新创建层次结构)。

有没有办法只在从 falsetrue 或相反时才发布?

示例场景:

我们在我们的应用程序中创建了一个用户对象,我们想向用户添加一辆汽车。如果没有找到汽车,应用程序应立即显示“添加汽车”视图,否则显示主应用程序视图。为此,我们在某处有一个听众。在我们的顶层视图中,我们有:


    @ObservedObject var viewModel = UserViewModel()


    var body: some View {
            if !viewModel.hasVehicles {
                return AnyView(AddVehicleView(viewModel:AddVehicleViewModel())
            } else {
                return AnyView(UserMainView(user: user))
            }
        }
    }

在我们的 UserViewModel 中有

class UserViewModel: ObservableObject {
    @Published var hasVehicles: Bool = false

  • 某些代码会在某些侦听器触发时更新该布尔值。

AddVehicleView 中,我们有一个表单,允许用户填写一些文本字段并保存车辆。

现在假设由于某种原因触发了更新 hasVehicles 属性的代码,但仍然没有车辆。会发生什么:

hasVehicles = false

并重新评估顶层视图,导致 return AnyView(AddVehicleView(viewModel:AddVehicleViewModel()) 被执行,并且我的带有文本字段的表单被清空。

我想在这种情况下我可以通过将 AddVehicleViewModel() 作为属性放在 View 结构中来解决它,但是在我们希望多次执行它的情况下无法解决它,因为这意味着下次构建视图时,它将显示我们上次创建该视图时的数据,因为我们重用了视图模型。

1 个答案:

答案 0 :(得分:1)

尝试将常规属性与手动发布商激活一起使用,例如

class UserViewModel: ObservableObject {
    var hasVehicles: Bool = false {
        willSet {
            if hasVehicles != newValue {
                objectWillChange.send()
            }
        }
    }
// ... other code
}