【问题标题】:iOS MVVM using Combine with Input/Outut pattern in UIKitiOS MVVM 在 UIKit 中使用结合输入/输出模式
【发布时间】: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 的代码链接。让我解释一下上面的代码

  1. 点击映射按钮触发 API 请求
  2. 将响应映射到输出

text 类型不是AnyPublisher&lt;String?, Never&gt;。看起来很奇怪

Publishers.Map&lt;AnyPublisher&lt;Publishers.FlatMap&lt;AnyPublisher&lt;Response?, Never&gt;, Publishers.Map&lt;PassthroughSubject&lt;Void, Never&gt;, ()&gt;&gt;.Output, Publishers.FlatMap&lt;AnyPublisher&lt;Response?, Never&gt;, Publishers.Map&lt;PassthroughSubject&lt;Void, Never&gt;, ()&gt;&gt;.Failure&gt;, String?&gt;

我的代码出了什么问题,如何使用 Combine 和 UIKit 制作输入/输出模式

【问题讨论】:

  • ViewModel.Output 需要 AnyPublisher 发布者...所以您需要匹配类型:Output(text: text.eraseToAnyPublisher)
  • 谢谢!有用。我不知道为什么我错过了这一点

标签: ios mvvm binding uikit combine


【解决方案1】:

您必须使用 eraseToAnyPublisher() 运算符擦除类型。

...
let text = response.map { $0?.text }.eraseToAnyPublisher()
...
output = Output(text: text)

【讨论】:

    猜你喜欢
    • 2021-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-05
    • 2018-06-30
    相关资源
    最近更新 更多