mvvm - 使用 SwiftUI/Combine,如何避免在 ViewModel 中放置可取消项
问题描述
我一直使用 RxSwift 将 DisposeBag 放在 MVVM 中的 ViewController 中,就像它在本主题中所说的那样:
在 iOS 上,对于 MVVM 中的 DisposeBag,可以放在 ViewModel 中吗?
但是使用组合,由于 View 是一个结构并且可取消的不能放在其中,我被困在解决方案中。
如何在合并中管理 View 和 VM 之间的订阅而不在 ViewModel 中添加可取消
或者,在 SwiftUI/Combine 中,没有选择在 VM 中放置可取消项。
在 SiwftUI / Combine 中有一个实现示例:
视图模型
class EquityViewModel: ObservableObject {
@Injected private var api: AlphaVantageAPI
private var cancellables = Set<AnyCancellable>()
private let code: String
@Published private var result: Quote?
@Published var price: String = ""
init(code: String) {
self.code = code
self.$result
.map {
return "\($0?.price ?? 0) €"
}.assign(to: &$price)
}
func addToPortfolio(){
}
func onAppear() {
self.api.quote(symbol: self.code).share()
.sink { completion in }
receiveValue: { quote in
self.result = quote.quote
}
.store(in: &cancellables)
}
}
风景
struct EquityView: View {
@ObservedObject var viewModel: EquityViewModel
init(viewModel: EquityViewModel) {
self.viewModel = viewModel
}
var body: some View {
ZStack {
Color("primary").edgesIgnoringSafeArea(.all)
VStack {
Text("Stock Price")
.foregroundColor(.white)
.frame(minWidth: 0,
maxWidth: .infinity,
alignment: .topLeading)
.padding()
HStack {
Text(self.viewModel.price)
.foregroundColor(.white)
Text("+4.75 %")
.foregroundColor(.white)
.padding(.leading, 20)
}.frame(minWidth: 0,
maxWidth: .infinity,
alignment: .topLeading)
.padding()
Button(action: self.viewModel.addToPortfolio, label: {
Text("Add to portfolio")
.foregroundColor(.white)
.frame(minWidth: 0,
maxWidth: .infinity,
maxHeight: 30,
alignment: .center)
.background(Color.blue)
.cornerRadius(5)
}).padding()
Spacer()
}
}.frame(alignment: .leading)
.onAppear(perform: self.viewModel.onAppear)
}
}
解决方案
你搜索的是什么?我无法测试它我不知道您使用的是什么库
class EquityViewMode: ObservableObject {
// @Injected private var api: AlphaVantageAPI
var pricePublisher: AnyPublisher<String, Never>
@Published var price: String = ""
init(){
// init your publisher like
// pricePublisher = self.api.quote(symbol: self.code)
// .share()
// .map { "\($0?.price ?? 0) €" }
// .eraseToAnyPublisher()
}
struct EquityView: View {
@ObservedObject var viewModel: EquityViewModel
var handle: AnyCancellable? = nil
init(m:EquityViewMode) {
viewModel = m
handle = m.pricePublisher.assign(to: \.price, on: self.viewModel)
}
var body: some View{
Text(viewModel.price)
}
}
推荐阅读
- android - 在android studio中错过资源
- python - 分布密度
- select - Select2 from select with required 不改变边框颜色。
- javascript - 在模态 PHP、Javascript 中根据 userId 显示 while 循环数据
- c# - 在 wpf datagrid 中的字符串属性中强制日期排序
- java - 如何以编程方式在布局点击位置添加视图?
- javascript - 在我的站点中使用我的 Python Web Crawler
- swift - 在 Swift 中使用正则表达式
- angular - 部署后的角度路由问题
- angular - Observable.combineLatest 不是函数