SwiftUI/ Combine 在 ObservableObject 中监听多个发布者
SwiftUI/ Combine Listen to multiple publishers inside an ObservableObject
我有一个 ObservableObject
,里面还有两个 ObservableObjects
。这两个 ObservableObject
中的每一个都有一个或多个 @Published
属性。我的解决方案有效,但我 100% 确定必须有另一种方法。我必须复制/粘贴所有内容才能使其正常工作。我尝试了两次将这两个发布者放在视图中,但随后我需要将很多参数传递给子视图。有什么想法可以简化吗?
class PackageService: ObservableObject {
@Published var package: Package
@Published var error: Error?
@Published var distance: Double?
@Published var expectedTravelTime: String?
@Published var amount: Int = 0
@Published var cost: Double = 0
@Published var annotations = [MKPointAnnotation]()
@Published var isCalculating = true
@Published var route: MKRoute?
var amountService = AmountService()
var routeService = RouteService()
private var cancellables = Set<AnyCancellable>()
init(package: Package) {
self.package = package
routeService.calcDirections(source: package.source.toCLLocationCoordinate2D, destination: package.destination.toCLLocationCoordinate2D)
routeService.$route.sink { [self] route in
self.route = route
amountService.calc(distance: route?.distance)
calc(route: route)
}
.store(in: &cancellables)
routeService.$isCalculating.sink { [self] isCalculating in
self.isCalculating = isCalculating
}
.store(in: &cancellables)
routeService.$error.sink { [self] error in
self.error = error
}
.store(in: &cancellables)
amountService.$amount.sink { [self] amount in
self.amount = amount
}
.store(in: &cancellables)
amountService.$cost.sink { [self] cost in
self.cost = cost
}
.store(in: &cancellables)
amountService.$error.sink { [self] error in
self.error = error
}
.store(in: &cancellables)
}
似乎 PackageService
只是其他两个服务的薄包装。
使用计算属性而不是为每个 属性:
订阅和发布更改是有意义的
var isCalculating: Bool { routeService.isCalculating }
var amount: Int { amountService.amount }
// etc...
并订阅一次以发出视图更改的信号:
routeService.objectWillChange
.merge(with: amountService.objectWillChange)
.sink(receiveValue: self.objectWillChange.send)
.store(in: &cancellables)
此外,考虑将各种属性打包到单个数据模型中,例如:
struct AmountModel {
var amount: Int
var cost: Double
}
并且 AmountService
有一个 属性。这可以是 Result<AmountModel, Error>
来捕获数据或错误,或者,如果需要,将 Error
作为 属性.
我有一个 ObservableObject
,里面还有两个 ObservableObjects
。这两个 ObservableObject
中的每一个都有一个或多个 @Published
属性。我的解决方案有效,但我 100% 确定必须有另一种方法。我必须复制/粘贴所有内容才能使其正常工作。我尝试了两次将这两个发布者放在视图中,但随后我需要将很多参数传递给子视图。有什么想法可以简化吗?
class PackageService: ObservableObject {
@Published var package: Package
@Published var error: Error?
@Published var distance: Double?
@Published var expectedTravelTime: String?
@Published var amount: Int = 0
@Published var cost: Double = 0
@Published var annotations = [MKPointAnnotation]()
@Published var isCalculating = true
@Published var route: MKRoute?
var amountService = AmountService()
var routeService = RouteService()
private var cancellables = Set<AnyCancellable>()
init(package: Package) {
self.package = package
routeService.calcDirections(source: package.source.toCLLocationCoordinate2D, destination: package.destination.toCLLocationCoordinate2D)
routeService.$route.sink { [self] route in
self.route = route
amountService.calc(distance: route?.distance)
calc(route: route)
}
.store(in: &cancellables)
routeService.$isCalculating.sink { [self] isCalculating in
self.isCalculating = isCalculating
}
.store(in: &cancellables)
routeService.$error.sink { [self] error in
self.error = error
}
.store(in: &cancellables)
amountService.$amount.sink { [self] amount in
self.amount = amount
}
.store(in: &cancellables)
amountService.$cost.sink { [self] cost in
self.cost = cost
}
.store(in: &cancellables)
amountService.$error.sink { [self] error in
self.error = error
}
.store(in: &cancellables)
}
似乎 PackageService
只是其他两个服务的薄包装。
使用计算属性而不是为每个 属性:
订阅和发布更改是有意义的var isCalculating: Bool { routeService.isCalculating }
var amount: Int { amountService.amount }
// etc...
并订阅一次以发出视图更改的信号:
routeService.objectWillChange
.merge(with: amountService.objectWillChange)
.sink(receiveValue: self.objectWillChange.send)
.store(in: &cancellables)
此外,考虑将各种属性打包到单个数据模型中,例如:
struct AmountModel {
var amount: Int
var cost: Double
}
并且 AmountService
有一个 属性。这可以是 Result<AmountModel, Error>
来捕获数据或错误,或者,如果需要,将 Error
作为 属性.