我正在学习MVVM + RxSwift。 我想保存一个值以在下一个流程中重用它。 但是我遇到了上面的错误。
我假设我初始化了一个名为“ translatedText”的值,但错误仍然出现。
我尝试了一些使用声明进行初始化的方法,等等...
import UIKit
import RxSwift
final class ViewModel {
private let api: apiProtocol
let validationText: Observable<String>
let getObservable: Observable<String>
var translatedText: String
// var translatedText: String = "" //this case also dosn't work
init(inputObservable: Observable<String?>, changeButtonClicked: Observable<Void>, model: ModelProtocol, api: apiProtocol = APICntl()) {
self.api = api
self.translatedText = "" //I guess I initialised this here
let event = inputObservable
.flatMap { input -> Observable<Event<Void>> in
if let text = input {
self.translatedText = text // error. i want to save "input" to use at "let tapEvent"
}
return model
.validate(text: input)
.materialize()
}
.share()
self.validationText = event
.flatMap { event -> Observable<String> in
switch event {
case .next:
return .just("")
case let .error(error as ModelError):
return .just(error.errorLabel)
case .error, .completed:
return .empty()
}
}
.startWith(ModelError.invalidBlank.errorLabel)
let tapEvent = changeButtonClicked
.flatMap { (result) -> Observable<Event<String>> in
return api
.fetch(text: self.translatedText) // I want use it here
.materialize()
}
.share()
self.getObservable = tapEvent
.flatMap { event -> Observable<String> in
switch event {
case .next:
return .just(event.element!)
case let .error(error as ModelError):
return .just(error.errorLabel)
case .error, .completed:
return .empty()
}
}
}
}
你们有更好的解决方案吗?
-----自我解决方案-----
我只是简单地在let事件之前创建了一个临时变量,它可以按我的意愿工作。
final class ViewModel {
private let api: apiProtocol
let validationText: Observable<String>
let getObservable: Observable<String>
init(inputObservable: Observable<String?>, changeButtonClicked: Observable<Void>, model: ModelProtocol, api: apiProtocol = APICntl()) {
self.api = api
var temp = ""
let event = inputObservable
.flatMap { input -> Observable<Event<Void>> in
if let text = input {
temp = text
}
return model
.validate(text: input)
.materialize()
}
.share()
答案 0 :(得分:0)
您的问题是,调用self
时flatMap
尚未完全初始化。就您而言,validationText
和getObservable
处于未定义状态。
最快的方法是使它们隐式地展开为可选,但是您实际上必须保证在初始化之前不会访问它们:
final class ViewModel {
private let api: apiProtocol
let validationText: Observable<String>!
let getObservable: Observable<String>!
var translatedText: String!
// ...
}
答案 1 :(得分:0)
----自我解决方案-----
我只是简单地在let事件之前创建了一个临时变量,它可以按我的意愿工作。
final class ViewModel {
private let api: apiProtocol
let validationText: Observable<String>
let getObservable: Observable<String>
init(inputObservable: Observable<String?>, changeButtonClicked: Observable<Void>, model: ModelProtocol, api: apiProtocol = APICntl()) {
self.api = api
var temp = ""
let event = inputObservable
.flatMap { input -> Observable<Event<Void>> in
if let text = input {
temp = text
}
return model
.validate(text: input)
.materialize()
}
.share()
答案 2 :(得分:0)
您不应将两个独立的可观察流与带有“ temp”内存的随机块相互绑定。这两个流取决于inputObservable
,应该明确说明。而且,您的视图模型可以大大简化...
final class ViewModel {
let validationText: Observable<String>
let getObservable: Observable<String>
init(inputObservable: Observable<String?>, changeButtonClicked: Observable<Void>, model: ModelProtocol, api: apiProtocol = APICntl()) {
let translatedText = inputObservable.share() // this line is unnecessary if `inputObservable` is already hot.
self.validationText = translatedText
.flatMap { input in
return model
.validate(text: input)
.map { "" }
.catchError { error in .just((error as? ModelError)?.errorLabel ?? error.localizedDescription) }
}
.startWith(ModelError.invalidBlank.errorLabel)
self.getObservable = changeButtonClicked
.withLatestFrom(translatedText)
.compactMap { $0 }
.flatMap { translatedText in
return api
.fetch(text: translatedText)
.catchError { error in .just((error as? ModelError)?.errorLabel ?? error.localizedDescription) }
}
}
}