是否有仅在值实际更改时发布的发布者?

  • 本文关键字:发布者 是否 swiftui combine
  • 更新时间 :
  • 英文 :


是否有办法使@Published变量仅在新值与旧值不同时发布其值?

现在如果我们有

@Published var test: Bool = false

,我们做

test = false
test = false
test = false

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

是否有一种方法只在从falsetrue时发布,反之亦然?

示例场景:

我们在应用程序中创建了一个user对象,我们想给这个用户添加一辆车。应用程序应该立即显示"添加汽车";视图,如果没有找到汽车,否则显示主应用程序视图。我们在某处有听众。在顶层视图中,我们有:


@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结构中的属性来解决它,但这不会解决它在我们想要执行多次的情况下,因为这意味着下次视图被构建时,它将显示上次我们创建该视图的数据,因为我们重用视图模型。

在更新属性的代码中使用Combine的removeDuplicates()操作符。例如,视图模型可以创建一个发布者,它根据另外两个布尔属性的值更新布尔属性:

@Published var hasTrucks: Bool
@Published var hasCars: Bool
@Published var hasVehicles: Bool
func createVehiclePublisher() {
Publishers.CombineLatest($hasTrucks, $hasCars)
.map { $0 || $1 }
.removeDuplicates()
.assign(to: &$hasVehicles)
}

使用removeDuplicates()会导致hasVehicles只有在其值发生变化时才会被更新。

尝试使用常规属性手动激活发布者,如

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

相关内容

最新更新