考虑到this post所描述的设计模式,这里是example view model:
final class SayHelloViewModel: ViewModelType {
let input: Input
let output: Output
struct Input {
let name: AnyObserver<String>
let validate: AnyObserver<Void>
}
struct Output {
let greeting: Driver<String>
}
private let nameSubject = ReplaySubject<String>.create(bufferSize: 1)
private let validateSubject = PublishSubject<Void>()
init() {
let greeting = validateSubject
.withLatestFrom(nameSubject)
.map { name in
return "Hello \(name)!"
}
.asDriver(onErrorJustReturn: ":-(")
self.output = Output(greeting: greeting)
self.input = Input(name: nameSubject.asObserver(), validate: validateSubject.asObserver())
}
}
以上似乎是一个完美的设计模式。我唯一的问题是,当您从nameSubject
-> greeting
的映射函数比此处显示的复杂得多,而需要抽象到它自己的函数中时,会发生什么?
在以下情况下,我已经将映射功能抽象为它自己的名为sayHello.
的函数。当然,现在的问题是,我们在初始化self之前先引用self。如何在非平凡的示例中保持这种设计模式?
final class SayHelloViewModel {
let input: Input
let output: Output
struct Input {
let name: AnyObserver<String>
let validate: AnyObserver<Void>
}
struct Output {
let greeting: Driver<String>
}
private let nameSubject = ReplaySubject<String>.create(bufferSize: 1)
private let validateSubject = PublishSubject<Void>()
init() {
let greeting = validateSubject
.withLatestFrom(nameSubject)
.map(sayHello)
.asDriver(onErrorJustReturn: ":-(")
self.output = Output(greeting: greeting)
self.input = Input(name: nameSubject.asObserver(), validate: validateSubject.asObserver())
}
private func sayHello(name: String) -> String {
return "Hello \(name)!"
}
}
只需将您的映射函数设为私有自由函数,而不是类成员。仅在需要访问成员时才需要成为成员本身,这种情况下这种可能性很小。
还提出了另一种可能的解决方案
final class SayHelloViewModel {
private let disposeBag = DisposeBag()
let input: Input
let output: Output
struct Input {
let name: AnyObserver<String>
let validate: AnyObserver<Void>
}
struct Output {
let greeting: Driver<String>
}
init() {
let nameSubject = ReplaySubject<String>.create(bufferSize: 1)
let validateSubject = PublishSubject<Void>()
let greeting = PublishSubject<String>()
output = Output(greeting: greeting.asDriver(onErrorJustReturn: ":-("))
input = Input(name: nameSubject.asObserver(), validate: validateSubject.asObserver())
validateSubject
.withLatestFrom(nameSubject)
.map(sayHello)
.bind(to: greeting)
.disposed(by: disposeBag)
}
private func sayHello(name: String) -> String {
return "Hello \(name)!"
}
}