我一直面临着在ViewModel中将UITextField或按钮与observables绑定的问题。
class VM {
var emailObservable: Observable<String?> = Observable.just("")
}
我在viewModel和控制器中有这个可观察的电子邮件。当我尝试用它绑定我的文本字段时,它给了我错误
无法使用'(to:Observable)'类型的参数列表调用'bind'。
但是当我用Variable替换observable时,它运行正常。
有人可以帮我解决这个问题。我发现答案主要包括在viewModel的init方法中传递observable,但我不想在init方法中传递它。
这是我发现绑定的链接,但它是通过init方法。
答案 0 :(得分:1)
我想这就是你要找的东西:
final class ViewModel {
private let bag = DisposeBag()
let string = BehaviorSubject<String>(value: "")
init() {
string.asObservable().subscribe(onNext: { string in
print(string)
})
.disposed(by: bag)
}
}
final class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
private let bag = DisposeBag()
private var viewModel: ViewModel!
override func viewDidLoad() {
super.viewDidLoad()
viewModel = ViewModel()
textField.rx.text
.orEmpty
.bind(to: viewModel.string)
.disposed(by: bag)
}
}
请注意,由于@MaximVolgin提及Variable
is deprecated in RxSwift 4,因此您可以使用BehaviorSubject
或其他由您决定的内容。
UPD。
仅使用Observable
实施。
final class ViewModel {
private let bag = DisposeBag()
var string = "" {
didSet {
print(string)
}
}
init(stringObservable: Observable<String>) {
stringObservable.subscribe(onNext: { string in
self.string = string
})
.disposed(by: bag)
}
}
final class ViewController: UIViewController {
@IBOutlet weak var textField: UITextField!
private let bag = DisposeBag()
private var viewModel: ViewModel!
override func viewDidLoad() {
super.viewDidLoad()
viewModel = ViewModel(stringObservable: textField.rx.text.orEmpty.asObservable())
}
}
如您所见,您的解决方案可以使用Observable
,而不是Variable
或任何类型的Subject
来实施。还应该提到的是,在大多数情况下,这不是最终的逻辑(只需将textField绑定到某个变量)。可以有一些验证,启用/禁用等逻辑。对于这种情况,RxSwift提供Driver
。关于在一个项目中使用Observable
和Driver
的差异的好例子可以在here找到(由RxSwift提供)。
答案 1 :(得分:0)
方法 .bind(to:)绑定到 Observer ,而不是 Observable 。
变量(在RxSwift v4中不推荐使用)是一个特殊用途的主题。
主题按照定义 Observer 和 Observable 。
这就是 .bind(to:)在里面做的事情 -
public func bind<O: ObserverType>(to observer: O) -> Disposable where O.E == E {
return self.subscribe(observer)
}
<强>更新强>
如何避免在VM的 .init()中传递observable:
// inside VM:
fileprivate let observableSwitch: BehaviorSubject<Observable<MyValue>>
fileprivate let myValueObservable = observableSwitch.switchLatest()
// instead of passing in init:
public func switch(to observable: Observable<MyValue>) {
self.observableSwitch.onNext(observable)
}
答案 2 :(得分:0)
在ViewModel类中使用变量类型的主题:
class ViewModel{
//MARK: - local Variables
var emailText = Variable<String?>("")
}
现在在viewController类中创建viewmodel类的对象,并将此emailtext变量绑定到viewcontroller中的textfield。每当textfield文本发生变化时,viewmodel的emailText都会获得值。
txtfield.rx.text
.bindTo(viewModel.emailText).addDisposableTo(disposeBag)
答案 3 :(得分:0)
而不是
emailTextfield.rx.text.asObservable().bind(to: viewModel.emailObservable).disposed(by: disposeBag)
使用此代码
viewModel.emailObservable.bind(to: noteField.rx.text).disposed(by: disposeBag)
您可能希望进行双向绑定,因此请详细了解here
答案 4 :(得分:0)
试试这个,
override func viewDidLoad() {
super.viewDidLoad()
_ = userNameTextField.rx.text.map { $0 ?? "" }.bind(to: viewModel.userName)
}
在viewModel类中,
class ViewModel{
var userName: Variable<String> = Variable("")
}