【发布时间】:2020-11-13 02:34:18
【问题描述】:
我正在尝试使用与 UIKit 结合的应用程序。我想用输入/输出模式实现 MVVM 架构
如果在 View/ViewController 中发生某些事情(例如视图生命周期事件或点击按钮等),它应该触发 API 请求,并且 View/ViewController 会对这些响应做出反应
这是我下面的代码
ViewModelType 协议
protocol ViewModelType {
associatedtype Input
associatedtype Output
var input: Input { get }
var output: Output { get }
}
Response模型
struct Response {
let text: String?
}
ViewMode类
class ViewModel: ViewModelType {
struct Input {
let buttonDidTapped: PassthroughSubject<Void, Never>
}
struct Output {
let text: AnyPublisher<String?, Never>
}
let input: Input
let output: Output
private var subscriptions = Set<AnyCancellable>()
init() {
let buttonDidTappedSubject = PassthroughSubject<Void, Never>()
let response = buttonDidTappedSubject.map { $0 }.flatMap(ViewModel.fetch).eraseToAnyPublisher() // ---- 1
let text = response.map { $0?.text } // ---- 2
input = Input(buttonDidTapped: buttonDidTappedSubject)
output = Output(text: text) // ---> Error!
}
private static func fetch() -> AnyPublisher<Response?, Never> {
return Future<Response?, Never> { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 1.0) {
promise(.success(Response(text: "Hello World")))
}
}.eraseToAnyPublisher()
}
}
我尝试在 ViewModel 的 init 方法中编写每个 Combine 的代码链接。让我解释一下上面的代码
- 点击映射按钮触发 API 请求
- 将响应映射到输出
但text 类型不是AnyPublisher<String?, Never>。看起来很奇怪
Publishers.Map<AnyPublisher<Publishers.FlatMap<AnyPublisher<Response?, Never>, Publishers.Map<PassthroughSubject<Void, Never>, ()>>.Output, Publishers.FlatMap<AnyPublisher<Response?, Never>, Publishers.Map<PassthroughSubject<Void, Never>, ()>>.Failure>, String?>
我的代码出了什么问题,如何使用 Combine 和 UIKit 制作输入/输出模式
【问题讨论】:
-
ViewModel.Output需要AnyPublisher发布者...所以您需要匹配类型:Output(text: text.eraseToAnyPublisher) -
谢谢!有用。我不知道为什么我错过了这一点
标签: ios mvvm binding uikit combine